diff --git a/contrib/llvm/FREEBSD-Xlist b/contrib/llvm/FREEBSD-Xlist index 9fbda5f3054..f694223a183 100644 --- a/contrib/llvm/FREEBSD-Xlist +++ b/contrib/llvm/FREEBSD-Xlist @@ -2,17 +2,15 @@ .arcconfig .clang-format .clang-tidy +.gitattributes .gitignore CMakeLists.txt CODE_OWNERS.TXT CREDITS.TXT LLVMBuild.txt -Makefile -Makefile.common -Makefile.config.in -Makefile.rules README.txt -autoconf/ +RELEASE_TESTERS.TXT +benchmarks/ bindings/ cmake/ configure @@ -21,473 +19,485 @@ examples/ include/llvm/CMakeLists.txt include/llvm/Config/ include/llvm/IR/CMakeLists.txt -include/llvm/Support/DataTypes.h.cmake +include/llvm/Support/CMakeLists.txt include/llvm/Support/LICENSE.TXT lib/Analysis/CMakeLists.txt -lib/Analysis/IPA/CMakeLists.txt -lib/Analysis/IPA/LLVMBuild.txt -lib/Analysis/IPA/Makefile lib/Analysis/LLVMBuild.txt -lib/Analysis/Makefile lib/Analysis/README.txt lib/AsmParser/CMakeLists.txt lib/AsmParser/LLVMBuild.txt -lib/AsmParser/Makefile +lib/BinaryFormat/CMakeLists.txt +lib/BinaryFormat/LLVMBuild.txt lib/Bitcode/CMakeLists.txt lib/Bitcode/LLVMBuild.txt -lib/Bitcode/Makefile lib/Bitcode/Reader/CMakeLists.txt lib/Bitcode/Reader/LLVMBuild.txt -lib/Bitcode/Reader/Makefile lib/Bitcode/Writer/CMakeLists.txt lib/Bitcode/Writer/LLVMBuild.txt -lib/Bitcode/Writer/Makefile lib/CMakeLists.txt lib/CodeGen/AsmPrinter/CMakeLists.txt lib/CodeGen/AsmPrinter/LLVMBuild.txt -lib/CodeGen/AsmPrinter/Makefile lib/CodeGen/CMakeLists.txt +lib/CodeGen/GlobalISel/CMakeLists.txt +lib/CodeGen/GlobalISel/LLVMBuild.txt lib/CodeGen/LLVMBuild.txt -lib/CodeGen/Makefile +lib/CodeGen/MIRParser/CMakeLists.txt +lib/CodeGen/MIRParser/LLVMBuild.txt lib/CodeGen/README.txt lib/CodeGen/SelectionDAG/CMakeLists.txt lib/CodeGen/SelectionDAG/LLVMBuild.txt -lib/CodeGen/SelectionDAG/Makefile lib/DebugInfo/CMakeLists.txt +lib/DebugInfo/CodeView/CMakeLists.txt +lib/DebugInfo/CodeView/LLVMBuild.txt lib/DebugInfo/DWARF/CMakeLists.txt lib/DebugInfo/DWARF/LLVMBuild.txt -lib/DebugInfo/DWARF/Makefile lib/DebugInfo/LLVMBuild.txt -lib/DebugInfo/Makefile +lib/DebugInfo/MSF/CMakeLists.txt +lib/DebugInfo/MSF/LLVMBuild.txt lib/DebugInfo/PDB/CMakeLists.txt lib/DebugInfo/PDB/LLVMBuild.txt -lib/DebugInfo/PDB/Makefile +lib/DebugInfo/Symbolize/CMakeLists.txt +lib/DebugInfo/Symbolize/LLVMBuild.txt +lib/Demangle/CMakeLists.txt +lib/Demangle/LLVMBuild.txt lib/ExecutionEngine/CMakeLists.txt lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt -lib/ExecutionEngine/IntelJITEvents/Makefile lib/ExecutionEngine/Interpreter/CMakeLists.txt lib/ExecutionEngine/Interpreter/LLVMBuild.txt -lib/ExecutionEngine/Interpreter/Makefile lib/ExecutionEngine/LLVMBuild.txt lib/ExecutionEngine/MCJIT/CMakeLists.txt lib/ExecutionEngine/MCJIT/LLVMBuild.txt -lib/ExecutionEngine/MCJIT/Makefile -lib/ExecutionEngine/Makefile lib/ExecutionEngine/OProfileJIT/CMakeLists.txt lib/ExecutionEngine/OProfileJIT/LLVMBuild.txt -lib/ExecutionEngine/OProfileJIT/Makefile lib/ExecutionEngine/Orc/CMakeLists.txt lib/ExecutionEngine/Orc/LLVMBuild.txt -lib/ExecutionEngine/Orc/Makefile +lib/ExecutionEngine/PerfJITEvents/CMakeLists.txt +lib/ExecutionEngine/PerfJITEvents/LLVMBuild.txt lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt lib/ExecutionEngine/RuntimeDyld/LLVMBuild.txt -lib/ExecutionEngine/RuntimeDyld/Makefile +lib/FuzzMutate/CMakeLists.txt +lib/FuzzMutate/LLVMBuild.txt lib/Fuzzer/ lib/IR/CMakeLists.txt lib/IR/LLVMBuild.txt -lib/IR/Makefile lib/IRReader/CMakeLists.txt lib/IRReader/LLVMBuild.txt -lib/IRReader/Makefile lib/LLVMBuild.txt lib/LTO/CMakeLists.txt lib/LTO/LLVMBuild.txt -lib/LTO/Makefile lib/LineEditor/CMakeLists.txt lib/LineEditor/LLVMBuild.txt -lib/LineEditor/Makefile lib/Linker/CMakeLists.txt lib/Linker/LLVMBuild.txt -lib/Linker/Makefile lib/MC/CMakeLists.txt lib/MC/LLVMBuild.txt lib/MC/MCDisassembler/CMakeLists.txt lib/MC/MCDisassembler/LLVMBuild.txt -lib/MC/MCDisassembler/Makefile lib/MC/MCParser/CMakeLists.txt lib/MC/MCParser/LLVMBuild.txt -lib/MC/MCParser/Makefile -lib/MC/Makefile -lib/Makefile +lib/MCA/CMakeLists.txt +lib/MCA/LLVMBuild.txt lib/Object/CMakeLists.txt lib/Object/LLVMBuild.txt -lib/Object/Makefile +lib/ObjectYAML/CMakeLists.txt +lib/ObjectYAML/LLVMBuild.txt +lib/OptRemarks/CMakeLists.txt +lib/OptRemarks/LLVMBuild.txt lib/Option/CMakeLists.txt lib/Option/LLVMBuild.txt -lib/Option/Makefile lib/Passes/CMakeLists.txt lib/Passes/LLVMBuild.txt -lib/Passes/Makefile lib/ProfileData/CMakeLists.txt +lib/ProfileData/Coverage/CMakeLists.txt +lib/ProfileData/Coverage/LLVMBuild.txt lib/ProfileData/LLVMBuild.txt -lib/ProfileData/Makefile lib/Support/CMakeLists.txt lib/Support/LLVMBuild.txt -lib/Support/Makefile lib/Support/README.txt.system lib/TableGen/CMakeLists.txt lib/TableGen/LLVMBuild.txt -lib/TableGen/Makefile lib/Target/AArch64/AsmParser/CMakeLists.txt lib/Target/AArch64/AsmParser/LLVMBuild.txt -lib/Target/AArch64/AsmParser/Makefile lib/Target/AArch64/CMakeLists.txt lib/Target/AArch64/Disassembler/CMakeLists.txt lib/Target/AArch64/Disassembler/LLVMBuild.txt -lib/Target/AArch64/Disassembler/Makefile lib/Target/AArch64/InstPrinter/CMakeLists.txt lib/Target/AArch64/InstPrinter/LLVMBuild.txt -lib/Target/AArch64/InstPrinter/Makefile lib/Target/AArch64/LLVMBuild.txt lib/Target/AArch64/MCTargetDesc/CMakeLists.txt lib/Target/AArch64/MCTargetDesc/LLVMBuild.txt -lib/Target/AArch64/MCTargetDesc/Makefile -lib/Target/AArch64/Makefile lib/Target/AArch64/TargetInfo/CMakeLists.txt lib/Target/AArch64/TargetInfo/LLVMBuild.txt -lib/Target/AArch64/TargetInfo/Makefile lib/Target/AArch64/Utils/CMakeLists.txt lib/Target/AArch64/Utils/LLVMBuild.txt -lib/Target/AArch64/Utils/Makefile +lib/Target/AMDGPU/AsmParser/CMakeLists.txt +lib/Target/AMDGPU/AsmParser/LLVMBuild.txt +lib/Target/AMDGPU/CMakeLists.txt +lib/Target/AMDGPU/Disassembler/CMakeLists.txt +lib/Target/AMDGPU/Disassembler/LLVMBuild.txt +lib/Target/AMDGPU/InstPrinter/CMakeLists.txt +lib/Target/AMDGPU/InstPrinter/LLVMBuild.txt +lib/Target/AMDGPU/LLVMBuild.txt +lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt +lib/Target/AMDGPU/MCTargetDesc/LLVMBuild.txt +lib/Target/AMDGPU/TargetInfo/CMakeLists.txt +lib/Target/AMDGPU/TargetInfo/LLVMBuild.txt +lib/Target/AMDGPU/Utils/CMakeLists.txt +lib/Target/AMDGPU/Utils/LLVMBuild.txt +lib/Target/ARC/CMakeLists.txt +lib/Target/ARC/Disassembler/CMakeLists.txt +lib/Target/ARC/Disassembler/LLVMBuild.txt +lib/Target/ARC/InstPrinter/CMakeLists.txt +lib/Target/ARC/InstPrinter/LLVMBuild.txt +lib/Target/ARC/LLVMBuild.txt +lib/Target/ARC/MCTargetDesc/CMakeLists.txt +lib/Target/ARC/MCTargetDesc/LLVMBuild.txt +lib/Target/ARC/TargetInfo/CMakeLists.txt +lib/Target/ARC/TargetInfo/LLVMBuild.txt lib/Target/ARM/AsmParser/CMakeLists.txt lib/Target/ARM/AsmParser/LLVMBuild.txt -lib/Target/ARM/AsmParser/Makefile lib/Target/ARM/CMakeLists.txt lib/Target/ARM/Disassembler/CMakeLists.txt lib/Target/ARM/Disassembler/LLVMBuild.txt -lib/Target/ARM/Disassembler/Makefile lib/Target/ARM/InstPrinter/CMakeLists.txt lib/Target/ARM/InstPrinter/LLVMBuild.txt -lib/Target/ARM/InstPrinter/Makefile lib/Target/ARM/LLVMBuild.txt lib/Target/ARM/MCTargetDesc/CMakeLists.txt lib/Target/ARM/MCTargetDesc/LLVMBuild.txt -lib/Target/ARM/MCTargetDesc/Makefile -lib/Target/ARM/Makefile lib/Target/ARM/README-Thumb.txt lib/Target/ARM/README-Thumb2.txt lib/Target/ARM/README.txt lib/Target/ARM/TargetInfo/CMakeLists.txt lib/Target/ARM/TargetInfo/LLVMBuild.txt -lib/Target/ARM/TargetInfo/Makefile +lib/Target/ARM/Utils/CMakeLists.txt +lib/Target/ARM/Utils/LLVMBuild.txt +lib/Target/AVR/AsmParser/CMakeLists.txt +lib/Target/AVR/AsmParser/LLVMBuild.txt +lib/Target/AVR/CMakeLists.txt +lib/Target/AVR/Disassembler/CMakeLists.txt +lib/Target/AVR/Disassembler/LLVMBuild.txt +lib/Target/AVR/InstPrinter/CMakeLists.txt +lib/Target/AVR/InstPrinter/LLVMBuild.txt +lib/Target/AVR/LLVMBuild.txt +lib/Target/AVR/MCTargetDesc/CMakeLists.txt +lib/Target/AVR/MCTargetDesc/LLVMBuild.txt +lib/Target/AVR/TargetInfo/CMakeLists.txt +lib/Target/AVR/TargetInfo/LLVMBuild.txt +lib/Target/BPF/AsmParser/CMakeLists.txt +lib/Target/BPF/AsmParser/LLVMBuild.txt lib/Target/BPF/CMakeLists.txt +lib/Target/BPF/Disassembler/CMakeLists.txt +lib/Target/BPF/Disassembler/LLVMBuild.txt lib/Target/BPF/InstPrinter/CMakeLists.txt lib/Target/BPF/InstPrinter/LLVMBuild.txt -lib/Target/BPF/InstPrinter/Makefile lib/Target/BPF/LLVMBuild.txt lib/Target/BPF/MCTargetDesc/CMakeLists.txt lib/Target/BPF/MCTargetDesc/LLVMBuild.txt -lib/Target/BPF/MCTargetDesc/Makefile -lib/Target/BPF/Makefile lib/Target/BPF/TargetInfo/CMakeLists.txt lib/Target/BPF/TargetInfo/LLVMBuild.txt -lib/Target/BPF/TargetInfo/Makefile lib/Target/CMakeLists.txt -lib/Target/CppBackend/CMakeLists.txt -lib/Target/CppBackend/LLVMBuild.txt -lib/Target/CppBackend/Makefile -lib/Target/CppBackend/TargetInfo/CMakeLists.txt -lib/Target/CppBackend/TargetInfo/LLVMBuild.txt -lib/Target/CppBackend/TargetInfo/Makefile +lib/Target/Hexagon/AsmParser/CMakeLists.txt +lib/Target/Hexagon/AsmParser/LLVMBuild.txt lib/Target/Hexagon/CMakeLists.txt lib/Target/Hexagon/Disassembler/CMakeLists.txt lib/Target/Hexagon/Disassembler/LLVMBuild.txt -lib/Target/Hexagon/Disassembler/Makefile lib/Target/Hexagon/LLVMBuild.txt lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt lib/Target/Hexagon/MCTargetDesc/LLVMBuild.txt -lib/Target/Hexagon/MCTargetDesc/Makefile -lib/Target/Hexagon/Makefile lib/Target/Hexagon/TargetInfo/CMakeLists.txt lib/Target/Hexagon/TargetInfo/LLVMBuild.txt -lib/Target/Hexagon/TargetInfo/Makefile lib/Target/LLVMBuild.txt +lib/Target/Lanai/AsmParser/CMakeLists.txt +lib/Target/Lanai/AsmParser/LLVMBuild.txt +lib/Target/Lanai/CMakeLists.txt +lib/Target/Lanai/Disassembler/CMakeLists.txt +lib/Target/Lanai/Disassembler/LLVMBuild.txt +lib/Target/Lanai/InstPrinter/CMakeLists.txt +lib/Target/Lanai/InstPrinter/LLVMBuild.txt +lib/Target/Lanai/LLVMBuild.txt +lib/Target/Lanai/MCTargetDesc/CMakeLists.txt +lib/Target/Lanai/MCTargetDesc/LLVMBuild.txt +lib/Target/Lanai/TargetInfo/CMakeLists.txt +lib/Target/Lanai/TargetInfo/LLVMBuild.txt +lib/Target/MSP430/AsmParser/CMakeLists.txt +lib/Target/MSP430/AsmParser/LLVMBuild.txt lib/Target/MSP430/CMakeLists.txt +lib/Target/MSP430/Disassembler/CMakeLists.txt +lib/Target/MSP430/Disassembler/LLVMBuild.txt lib/Target/MSP430/InstPrinter/CMakeLists.txt lib/Target/MSP430/InstPrinter/LLVMBuild.txt -lib/Target/MSP430/InstPrinter/Makefile lib/Target/MSP430/LLVMBuild.txt lib/Target/MSP430/MCTargetDesc/CMakeLists.txt lib/Target/MSP430/MCTargetDesc/LLVMBuild.txt -lib/Target/MSP430/MCTargetDesc/Makefile -lib/Target/MSP430/Makefile lib/Target/MSP430/README.txt lib/Target/MSP430/TargetInfo/CMakeLists.txt lib/Target/MSP430/TargetInfo/LLVMBuild.txt -lib/Target/MSP430/TargetInfo/Makefile -lib/Target/Makefile lib/Target/Mips/AsmParser/CMakeLists.txt lib/Target/Mips/AsmParser/LLVMBuild.txt -lib/Target/Mips/AsmParser/Makefile lib/Target/Mips/CMakeLists.txt lib/Target/Mips/Disassembler/CMakeLists.txt lib/Target/Mips/Disassembler/LLVMBuild.txt -lib/Target/Mips/Disassembler/Makefile lib/Target/Mips/InstPrinter/CMakeLists.txt lib/Target/Mips/InstPrinter/LLVMBuild.txt -lib/Target/Mips/InstPrinter/Makefile lib/Target/Mips/LLVMBuild.txt lib/Target/Mips/MCTargetDesc/CMakeLists.txt lib/Target/Mips/MCTargetDesc/LLVMBuild.txt -lib/Target/Mips/MCTargetDesc/Makefile -lib/Target/Mips/Makefile lib/Target/Mips/TargetInfo/CMakeLists.txt lib/Target/Mips/TargetInfo/LLVMBuild.txt -lib/Target/Mips/TargetInfo/Makefile lib/Target/NVPTX/CMakeLists.txt lib/Target/NVPTX/InstPrinter/CMakeLists.txt lib/Target/NVPTX/InstPrinter/LLVMBuild.txt -lib/Target/NVPTX/InstPrinter/Makefile lib/Target/NVPTX/LLVMBuild.txt lib/Target/NVPTX/MCTargetDesc/CMakeLists.txt lib/Target/NVPTX/MCTargetDesc/LLVMBuild.txt -lib/Target/NVPTX/MCTargetDesc/Makefile -lib/Target/NVPTX/Makefile lib/Target/NVPTX/TargetInfo/CMakeLists.txt lib/Target/NVPTX/TargetInfo/LLVMBuild.txt -lib/Target/NVPTX/TargetInfo/Makefile lib/Target/PowerPC/AsmParser/CMakeLists.txt lib/Target/PowerPC/AsmParser/LLVMBuild.txt -lib/Target/PowerPC/AsmParser/Makefile lib/Target/PowerPC/CMakeLists.txt lib/Target/PowerPC/Disassembler/CMakeLists.txt lib/Target/PowerPC/Disassembler/LLVMBuild.txt -lib/Target/PowerPC/Disassembler/Makefile lib/Target/PowerPC/InstPrinter/CMakeLists.txt lib/Target/PowerPC/InstPrinter/LLVMBuild.txt -lib/Target/PowerPC/InstPrinter/Makefile lib/Target/PowerPC/LLVMBuild.txt lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt lib/Target/PowerPC/MCTargetDesc/LLVMBuild.txt -lib/Target/PowerPC/MCTargetDesc/Makefile -lib/Target/PowerPC/Makefile lib/Target/PowerPC/README.txt lib/Target/PowerPC/README_ALTIVEC.txt lib/Target/PowerPC/TargetInfo/CMakeLists.txt lib/Target/PowerPC/TargetInfo/LLVMBuild.txt -lib/Target/PowerPC/TargetInfo/Makefile -lib/Target/R600/AsmParser/CMakeLists.txt -lib/Target/R600/AsmParser/LLVMBuild.txt -lib/Target/R600/AsmParser/Makefile -lib/Target/R600/CMakeLists.txt -lib/Target/R600/InstPrinter/CMakeLists.txt -lib/Target/R600/InstPrinter/LLVMBuild.txt -lib/Target/R600/InstPrinter/Makefile -lib/Target/R600/LLVMBuild.txt -lib/Target/R600/MCTargetDesc/CMakeLists.txt -lib/Target/R600/MCTargetDesc/LLVMBuild.txt -lib/Target/R600/MCTargetDesc/Makefile -lib/Target/R600/Makefile -lib/Target/R600/TargetInfo/CMakeLists.txt -lib/Target/R600/TargetInfo/LLVMBuild.txt -lib/Target/R600/TargetInfo/Makefile lib/Target/README.txt +lib/Target/RISCV/AsmParser/CMakeLists.txt +lib/Target/RISCV/AsmParser/LLVMBuild.txt +lib/Target/RISCV/CMakeLists.txt +lib/Target/RISCV/Disassembler/CMakeLists.txt +lib/Target/RISCV/Disassembler/LLVMBuild.txt +lib/Target/RISCV/InstPrinter/CMakeLists.txt +lib/Target/RISCV/InstPrinter/LLVMBuild.txt +lib/Target/RISCV/LLVMBuild.txt +lib/Target/RISCV/MCTargetDesc/CMakeLists.txt +lib/Target/RISCV/MCTargetDesc/LLVMBuild.txt +lib/Target/RISCV/TargetInfo/CMakeLists.txt +lib/Target/RISCV/TargetInfo/LLVMBuild.txt +lib/Target/RISCV/Utils/CMakeLists.txt +lib/Target/RISCV/Utils/LLVMBuild.txt lib/Target/Sparc/AsmParser/CMakeLists.txt lib/Target/Sparc/AsmParser/LLVMBuild.txt -lib/Target/Sparc/AsmParser/Makefile lib/Target/Sparc/CMakeLists.txt lib/Target/Sparc/Disassembler/CMakeLists.txt lib/Target/Sparc/Disassembler/LLVMBuild.txt -lib/Target/Sparc/Disassembler/Makefile lib/Target/Sparc/InstPrinter/CMakeLists.txt lib/Target/Sparc/InstPrinter/LLVMBuild.txt -lib/Target/Sparc/InstPrinter/Makefile lib/Target/Sparc/LLVMBuild.txt lib/Target/Sparc/MCTargetDesc/CMakeLists.txt lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt -lib/Target/Sparc/MCTargetDesc/Makefile -lib/Target/Sparc/Makefile lib/Target/Sparc/README.txt lib/Target/Sparc/TargetInfo/CMakeLists.txt lib/Target/Sparc/TargetInfo/LLVMBuild.txt -lib/Target/Sparc/TargetInfo/Makefile lib/Target/SystemZ/AsmParser/CMakeLists.txt lib/Target/SystemZ/AsmParser/LLVMBuild.txt -lib/Target/SystemZ/AsmParser/Makefile lib/Target/SystemZ/CMakeLists.txt lib/Target/SystemZ/Disassembler/CMakeLists.txt lib/Target/SystemZ/Disassembler/LLVMBuild.txt -lib/Target/SystemZ/Disassembler/Makefile lib/Target/SystemZ/InstPrinter/CMakeLists.txt lib/Target/SystemZ/InstPrinter/LLVMBuild.txt -lib/Target/SystemZ/InstPrinter/Makefile lib/Target/SystemZ/LLVMBuild.txt lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt lib/Target/SystemZ/MCTargetDesc/LLVMBuild.txt -lib/Target/SystemZ/MCTargetDesc/Makefile -lib/Target/SystemZ/Makefile lib/Target/SystemZ/TargetInfo/CMakeLists.txt lib/Target/SystemZ/TargetInfo/LLVMBuild.txt -lib/Target/SystemZ/TargetInfo/Makefile +lib/Target/WebAssembly/AsmParser/CMakeLists.txt +lib/Target/WebAssembly/AsmParser/LLVMBuild.txt +lib/Target/WebAssembly/CMakeLists.txt +lib/Target/WebAssembly/Disassembler/CMakeLists.txt +lib/Target/WebAssembly/Disassembler/LLVMBuild.txt +lib/Target/WebAssembly/InstPrinter/CMakeLists.txt +lib/Target/WebAssembly/InstPrinter/LLVMBuild.txt +lib/Target/WebAssembly/LLVMBuild.txt +lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt +lib/Target/WebAssembly/MCTargetDesc/LLVMBuild.txt +lib/Target/WebAssembly/TargetInfo/CMakeLists.txt +lib/Target/WebAssembly/TargetInfo/LLVMBuild.txt lib/Target/X86/AsmParser/CMakeLists.txt lib/Target/X86/AsmParser/LLVMBuild.txt -lib/Target/X86/AsmParser/Makefile lib/Target/X86/CMakeLists.txt lib/Target/X86/Disassembler/CMakeLists.txt lib/Target/X86/Disassembler/LLVMBuild.txt -lib/Target/X86/Disassembler/Makefile lib/Target/X86/InstPrinter/CMakeLists.txt lib/Target/X86/InstPrinter/LLVMBuild.txt -lib/Target/X86/InstPrinter/Makefile lib/Target/X86/LLVMBuild.txt lib/Target/X86/MCTargetDesc/CMakeLists.txt lib/Target/X86/MCTargetDesc/LLVMBuild.txt -lib/Target/X86/MCTargetDesc/Makefile -lib/Target/X86/Makefile lib/Target/X86/README-FPStack.txt -lib/Target/X86/README-MMX.txt lib/Target/X86/README-SSE.txt -lib/Target/X86/README-UNIMPLEMENTED.txt lib/Target/X86/README-X86-64.txt lib/Target/X86/README.txt lib/Target/X86/TargetInfo/CMakeLists.txt lib/Target/X86/TargetInfo/LLVMBuild.txt -lib/Target/X86/TargetInfo/Makefile lib/Target/X86/Utils/CMakeLists.txt lib/Target/X86/Utils/LLVMBuild.txt -lib/Target/X86/Utils/Makefile -lib/Target/X86/X86CompilationCallback_Win64.asm lib/Target/XCore/CMakeLists.txt lib/Target/XCore/Disassembler/CMakeLists.txt lib/Target/XCore/Disassembler/LLVMBuild.txt -lib/Target/XCore/Disassembler/Makefile lib/Target/XCore/InstPrinter/CMakeLists.txt lib/Target/XCore/InstPrinter/LLVMBuild.txt -lib/Target/XCore/InstPrinter/Makefile lib/Target/XCore/LLVMBuild.txt lib/Target/XCore/MCTargetDesc/CMakeLists.txt lib/Target/XCore/MCTargetDesc/LLVMBuild.txt -lib/Target/XCore/MCTargetDesc/Makefile -lib/Target/XCore/Makefile lib/Target/XCore/README.txt lib/Target/XCore/TargetInfo/CMakeLists.txt lib/Target/XCore/TargetInfo/LLVMBuild.txt -lib/Target/XCore/TargetInfo/Makefile +lib/Testing/CMakeLists.txt +lib/Testing/LLVMBuild.txt +lib/Testing/Support/CMakeLists.txt +lib/Testing/Support/LLVMBuild.txt +lib/TextAPI/CMakeLists.txt +lib/TextAPI/LLVMBuild.txt +lib/ToolDrivers/CMakeLists.txt +lib/ToolDrivers/LLVMBuild.txt +lib/ToolDrivers/llvm-dlltool/CMakeLists.txt +lib/ToolDrivers/llvm-dlltool/LLVMBuild.txt +lib/ToolDrivers/llvm-lib/CMakeLists.txt +lib/ToolDrivers/llvm-lib/LLVMBuild.txt +lib/Transforms/AggressiveInstCombine/CMakeLists.txt +lib/Transforms/AggressiveInstCombine/LLVMBuild.txt lib/Transforms/CMakeLists.txt +lib/Transforms/Coroutines/CMakeLists.txt +lib/Transforms/Coroutines/LLVMBuild.txt lib/Transforms/Hello/ lib/Transforms/IPO/CMakeLists.txt lib/Transforms/IPO/LLVMBuild.txt -lib/Transforms/IPO/Makefile lib/Transforms/InstCombine/CMakeLists.txt lib/Transforms/InstCombine/LLVMBuild.txt -lib/Transforms/InstCombine/Makefile lib/Transforms/Instrumentation/CMakeLists.txt lib/Transforms/Instrumentation/LLVMBuild.txt -lib/Transforms/Instrumentation/Makefile lib/Transforms/LLVMBuild.txt -lib/Transforms/Makefile lib/Transforms/ObjCARC/CMakeLists.txt lib/Transforms/ObjCARC/LLVMBuild.txt -lib/Transforms/ObjCARC/Makefile lib/Transforms/Scalar/CMakeLists.txt lib/Transforms/Scalar/LLVMBuild.txt -lib/Transforms/Scalar/Makefile lib/Transforms/Utils/CMakeLists.txt lib/Transforms/Utils/LLVMBuild.txt -lib/Transforms/Utils/Makefile lib/Transforms/Vectorize/CMakeLists.txt lib/Transforms/Vectorize/LLVMBuild.txt -lib/Transforms/Vectorize/Makefile +lib/WindowsManifest/CMakeLists.txt +lib/WindowsManifest/LLVMBuild.txt +lib/XRay/CMakeLists.txt +lib/XRay/LLVMBuild.txt llvm.spec.in -projects/ +projects/CMakeLists.txt +projects/LLVMBuild.txt +resources/ +runtimes/ test/ tools/CMakeLists.txt tools/LLVMBuild.txt -tools/Makefile +tools/bugpoint-passes/ tools/bugpoint/CMakeLists.txt tools/bugpoint/LLVMBuild.txt -tools/bugpoint/Makefile -tools/bugpoint-passes/ tools/dsymutil/ tools/gold/ tools/llc/CMakeLists.txt tools/llc/LLVMBuild.txt -tools/llc/Makefile tools/lli/CMakeLists.txt tools/lli/ChildTarget/CMakeLists.txt tools/lli/ChildTarget/LLVMBuild.txt -tools/lli/ChildTarget/Makefile tools/lli/LLVMBuild.txt -tools/lli/Makefile tools/llvm-ar/CMakeLists.txt tools/llvm-ar/LLVMBuild.txt -tools/llvm-ar/Makefile -tools/llvm-ar/install_symlink.cmake +tools/llvm-as-fuzzer/ +tools/llvm-as-parasitic-coverage-repro/ tools/llvm-as/CMakeLists.txt tools/llvm-as/LLVMBuild.txt -tools/llvm-as/Makefile tools/llvm-bcanalyzer/CMakeLists.txt tools/llvm-bcanalyzer/LLVMBuild.txt -tools/llvm-bcanalyzer/Makefile tools/llvm-c-test/ +tools/llvm-cat/ +tools/llvm-cfi-verify/ tools/llvm-config/ tools/llvm-cov/CMakeLists.txt tools/llvm-cov/LLVMBuild.txt -tools/llvm-cov/Makefile +tools/llvm-cvtres/ tools/llvm-cxxdump/CMakeLists.txt tools/llvm-cxxdump/LLVMBuild.txt -tools/llvm-cxxdump/Makefile +tools/llvm-cxxfilt/CMakeLists.txt +tools/llvm-cxxmap/CMakeLists.txt +tools/llvm-cxxmap/LLVMBuild.txt tools/llvm-diff/CMakeLists.txt tools/llvm-diff/LLVMBuild.txt -tools/llvm-diff/Makefile tools/llvm-dis/CMakeLists.txt tools/llvm-dis/LLVMBuild.txt -tools/llvm-dis/Makefile tools/llvm-dwarfdump/CMakeLists.txt tools/llvm-dwarfdump/LLVMBuild.txt -tools/llvm-dwarfdump/Makefile +tools/llvm-dwarfdump/fuzzer/ +tools/llvm-dwp/ +tools/llvm-elfabi/ +tools/llvm-exegesis/ tools/llvm-extract/CMakeLists.txt tools/llvm-extract/LLVMBuild.txt -tools/llvm-extract/Makefile tools/llvm-go/ +tools/llvm-isel-fuzzer/ +tools/llvm-itanium-demangle-fuzzer/ tools/llvm-jitlistener/ tools/llvm-link/CMakeLists.txt tools/llvm-link/LLVMBuild.txt -tools/llvm-link/Makefile tools/llvm-lto/CMakeLists.txt tools/llvm-lto/LLVMBuild.txt -tools/llvm-lto/Makefile +tools/llvm-lto2/CMakeLists.txt +tools/llvm-lto2/LLVMBuild.txt +tools/llvm-mc-assemble-fuzzer/ +tools/llvm-mc-disassemble-fuzzer/ tools/llvm-mc/CMakeLists.txt tools/llvm-mc/LLVMBuild.txt -tools/llvm-mc/Makefile +tools/llvm-mca/CMakeLists.txt +tools/llvm-mca/LLVMBuild.txt tools/llvm-mcmarkup/ +tools/llvm-microsoft-demangle-fuzzer/ +tools/llvm-modextract/CMakeLists.txt +tools/llvm-modextract/LLVMBuild.txt +tools/llvm-mt/ tools/llvm-nm/CMakeLists.txt tools/llvm-nm/LLVMBuild.txt -tools/llvm-nm/Makefile +tools/llvm-objcopy/CMakeLists.txt +tools/llvm-objcopy/LLVMBuild.txt tools/llvm-objdump/CMakeLists.txt tools/llvm-objdump/LLVMBuild.txt -tools/llvm-objdump/Makefile -tools/llvm-pdbdump/CMakeLists.txt -tools/llvm-pdbdump/LLVMBuild.txt -tools/llvm-pdbdump/Makefile +tools/llvm-opt-fuzzer/ +tools/llvm-opt-report/ +tools/llvm-pdbutil/CMakeLists.txt +tools/llvm-pdbutil/LLVMBuild.txt +tools/llvm-pdbutil/fuzzer/ tools/llvm-profdata/CMakeLists.txt tools/llvm-profdata/LLVMBuild.txt -tools/llvm-profdata/Makefile +tools/llvm-rc/ tools/llvm-readobj/CMakeLists.txt tools/llvm-readobj/LLVMBuild.txt -tools/llvm-readobj/Makefile tools/llvm-rtdyld/CMakeLists.txt tools/llvm-rtdyld/LLVMBuild.txt -tools/llvm-rtdyld/Makefile tools/llvm-shlib/ tools/llvm-size/ +tools/llvm-special-case-list-fuzzer/ +tools/llvm-split/ tools/llvm-stress/CMakeLists.txt tools/llvm-stress/LLVMBuild.txt -tools/llvm-stress/Makefile +tools/llvm-strings/ tools/llvm-symbolizer/CMakeLists.txt -tools/llvm-symbolizer/Makefile +tools/llvm-undname/ tools/llvm-vtabledump/ +tools/llvm-xray/CMakeLists.txt +tools/llvm-yaml-numeric-parser-fuzzer/ tools/lto/ -tools/macho-dump/CMakeLists.txt -tools/macho-dump/LLVMBuild.txt -tools/macho-dump/Makefile tools/msbuild/ tools/obj2yaml/ +tools/opt-remarks/ +tools/opt-viewer/ tools/opt/CMakeLists.txt tools/opt/LLVMBuild.txt -tools/opt/Makefile +tools/sancov/ +tools/sanstats/ tools/verify-uselistorder/ +tools/xcode-toolchain/ tools/yaml2obj/ unittests/ utils/DSAclean.py @@ -498,33 +508,47 @@ utils/GetRepositoryPath utils/GetSourceVersion utils/KillTheDoctor/ utils/LLVMBuild.txt -utils/Makefile +utils/LLVMVisualizers/ utils/Misc/ utils/PerfectShuffle/ +utils/Reviewing/ utils/TableGen/CMakeLists.txt utils/TableGen/LLVMBuild.txt -utils/TableGen/Makefile utils/TableGen/tdtags utils/Target/ utils/UpdateCMakeLists.pl +utils/UpdateTestChecks/ +utils/abtest/ +utils/abtest.py +utils/benchmark/ utils/bisect +utils/bisect-skip-count utils/bugpoint/ +utils/bugpoint_gisel_reducer.py utils/buildit/ utils/check-each-file utils/clang-parse-diagnostics-file utils/codegen-diff +utils/collect_and_build_with_pgo.py utils/count/ utils/countloc.sh utils/create_ladder_graph.py utils/crosstool/ +utils/demangle_tree.py +utils/docker/ utils/emacs/ +utils/extract_symbols.py +utils/extract_vplan.py utils/findmisopt utils/findoptdiff utils/findsym.pl utils/fpcmp/ +utils/gdb-scripts/ utils/getsrcs.sh utils/git/ utils/git-svn/ +utils/gn/ +utils/indirect_calls.py utils/jedit/ utils/kate/ utils/lint/ @@ -532,23 +556,33 @@ utils/lit/ utils/lldbDataFormatters.py utils/llvm-build/ utils/llvm-compilers-check +utils/llvm-gisel-cov.py utils/llvm-lit/ utils/llvm-native-gxx utils/llvm.grm -utils/llvm.natvis utils/llvmdo utils/llvmgrep -utils/makellvm utils/not/ +utils/opt-viewer/ +utils/prepare-code-coverage-artifact.py utils/release/ +utils/sanitizers/ +utils/schedcover.py utils/shuffle_fuzz.py +utils/shuffle_select_fuzz_tester.py utils/sort_includes.py -utils/test_debuginfo.pl utils/testgen/ utils/textmate/ +utils/unicode-case-fold.py utils/unittest/ +utils/update_analyze_test_checks.py +utils/update_cc_test_checks.py utils/update_llc_test_checks.py +utils/update_mca_test_checks.py +utils/update_mir_test_checks.py +utils/update_test_checks.py utils/valgrind/ utils/vim/ +utils/vscode/ utils/wciia.py utils/yaml-bench/ diff --git a/contrib/llvm/LICENSE.TXT b/contrib/llvm/LICENSE.TXT index 461398bab7a..e4d67d16fea 100644 --- a/contrib/llvm/LICENSE.TXT +++ b/contrib/llvm/LICENSE.TXT @@ -4,7 +4,7 @@ LLVM Release License University of Illinois/NCSA Open Source License -Copyright (c) 2003-2018 University of Illinois at Urbana-Champaign. +Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: diff --git a/contrib/llvm/include/llvm-c/Core.h b/contrib/llvm/include/llvm-c/Core.h index 6792219f873..06de058bdc5 100644 --- a/contrib/llvm/include/llvm-c/Core.h +++ b/contrib/llvm/include/llvm-c/Core.h @@ -54,6 +54,8 @@ extern "C" { * @{ */ +/// External users depend on the following values being stable. It is not safe +/// to reorder them. typedef enum { /* Terminator Instructions */ LLVMRet = 1, @@ -64,6 +66,9 @@ typedef enum { /* removed 6 due to API changes */ LLVMUnreachable = 7, + /* Standard Unary Operators */ + LLVMFNeg = 66, + /* Standard Binary Operators */ LLVMAdd = 8, LLVMFAdd = 9, @@ -515,6 +520,23 @@ void *LLVMContextGetDiagnosticContext(LLVMContextRef C); void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback Callback, void *OpaqueHandle); +/** + * Retrieve whether the given context is set to discard all value names. + * + * @see LLVMContext::shouldDiscardValueNames() + */ +LLVMBool LLVMContextShouldDiscardValueNames(LLVMContextRef C); + +/** + * Set whether the given context discards all value names. + * + * If true, only the names of GlobalValue objects will be available in the IR. + * This can be used to save memory and runtime, especially in release mode. + * + * @see LLVMContext::setDiscardValueNames() + */ +void LLVMContextSetDiscardValueNames(LLVMContextRef C, LLVMBool Discard); + /** * Destroy a context instance. * @@ -842,6 +864,63 @@ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M); */ LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name); +/** + * Obtain an iterator to the first NamedMDNode in a Module. + * + * @see llvm::Module::named_metadata_begin() + */ +LLVMNamedMDNodeRef LLVMGetFirstNamedMetadata(LLVMModuleRef M); + +/** + * Obtain an iterator to the last NamedMDNode in a Module. + * + * @see llvm::Module::named_metadata_end() + */ +LLVMNamedMDNodeRef LLVMGetLastNamedMetadata(LLVMModuleRef M); + +/** + * Advance a NamedMDNode iterator to the next NamedMDNode. + * + * Returns NULL if the iterator was already at the end and there are no more + * named metadata nodes. + */ +LLVMNamedMDNodeRef LLVMGetNextNamedMetadata(LLVMNamedMDNodeRef NamedMDNode); + +/** + * Decrement a NamedMDNode iterator to the previous NamedMDNode. + * + * Returns NULL if the iterator was already at the beginning and there are + * no previous named metadata nodes. + */ +LLVMNamedMDNodeRef LLVMGetPreviousNamedMetadata(LLVMNamedMDNodeRef NamedMDNode); + +/** + * Retrieve a NamedMDNode with the given name, returning NULL if no such + * node exists. + * + * @see llvm::Module::getNamedMetadata() + */ +LLVMNamedMDNodeRef LLVMGetNamedMetadata(LLVMModuleRef M, + const char *Name, size_t NameLen); + +/** + * Retrieve a NamedMDNode with the given name, creating a new node if no such + * node exists. + * + * @see llvm::Module::getOrInsertNamedMetadata() + */ +LLVMNamedMDNodeRef LLVMGetOrInsertNamedMetadata(LLVMModuleRef M, + const char *Name, + size_t NameLen); + +/** + * Retrieve the name of a NamedMDNode. + * + * @see llvm::NamedMDNode::getName() + */ +const char *LLVMGetNamedMetadataName(LLVMNamedMDNodeRef NamedMD, + size_t *NameLen); + /** * Obtain the number of operands for named metadata in a module. * @@ -872,6 +951,44 @@ void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char *Name, void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char *Name, LLVMValueRef Val); +/** + * Return the directory of the debug location for this value, which must be + * an llvm::Instruction, llvm::GlobalVariable, or llvm::Function. + * + * @see llvm::Instruction::getDebugLoc() + * @see llvm::GlobalVariable::getDebugInfo() + * @see llvm::Function::getSubprogram() + */ +const char *LLVMGetDebugLocDirectory(LLVMValueRef Val, unsigned *Length); + +/** + * Return the filename of the debug location for this value, which must be + * an llvm::Instruction, llvm::GlobalVariable, or llvm::Function. + * + * @see llvm::Instruction::getDebugLoc() + * @see llvm::GlobalVariable::getDebugInfo() + * @see llvm::Function::getSubprogram() + */ +const char *LLVMGetDebugLocFilename(LLVMValueRef Val, unsigned *Length); + +/** + * Return the line number of the debug location for this value, which must be + * an llvm::Instruction, llvm::GlobalVariable, or llvm::Function. + * + * @see llvm::Instruction::getDebugLoc() + * @see llvm::GlobalVariable::getDebugInfo() + * @see llvm::Function::getSubprogram() + */ +unsigned LLVMGetDebugLocLine(LLVMValueRef Val); + +/** + * Return the column number of the debug location for this value, which must be + * an llvm::Instruction. + * + * @see llvm::Instruction::getDebugLoc() + */ +unsigned LLVMGetDebugLocColumn(LLVMValueRef Val); + /** * Add a function to a module under a specified name. * @@ -1221,6 +1338,13 @@ LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy); */ LLVMBool LLVMIsOpaqueStruct(LLVMTypeRef StructTy); +/** + * Determine whether a structure is literal. + * + * @see llvm::StructType::isLiteral() + */ +LLVMBool LLVMIsLiteralStruct(LLVMTypeRef StructTy); + /** * @} */ @@ -1408,6 +1532,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(ConstantVector) \ macro(GlobalValue) \ macro(GlobalAlias) \ + macro(GlobalIFunc) \ macro(GlobalObject) \ macro(Function) \ macro(GlobalVariable) \ @@ -1417,7 +1542,9 @@ LLVMTypeRef LLVMX86MMXType(void); macro(CallInst) \ macro(IntrinsicInst) \ macro(DbgInfoIntrinsic) \ - macro(DbgDeclareInst) \ + macro(DbgVariableIntrinsic) \ + macro(DbgDeclareInst) \ + macro(DbgLabelInst) \ macro(MemIntrinsic) \ macro(MemCpyInst) \ macro(MemMoveInst) \ @@ -1434,16 +1561,15 @@ LLVMTypeRef LLVMX86MMXType(void); macro(SelectInst) \ macro(ShuffleVectorInst) \ macro(StoreInst) \ - macro(TerminatorInst) \ - macro(BranchInst) \ - macro(IndirectBrInst) \ - macro(InvokeInst) \ - macro(ReturnInst) \ - macro(SwitchInst) \ - macro(UnreachableInst) \ - macro(ResumeInst) \ - macro(CleanupReturnInst) \ - macro(CatchReturnInst) \ + macro(BranchInst) \ + macro(IndirectBrInst) \ + macro(InvokeInst) \ + macro(ReturnInst) \ + macro(SwitchInst) \ + macro(UnreachableInst) \ + macro(ResumeInst) \ + macro(CleanupReturnInst) \ + macro(CatchReturnInst) \ macro(FuncletPadInst) \ macro(CatchPadInst) \ macro(CleanupPadInst) \ @@ -1959,9 +2085,14 @@ LLVMValueRef LLVMConstLShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstGEP(LLVMValueRef ConstantVal, LLVMValueRef *ConstantIndices, unsigned NumIndices); +LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, unsigned NumIndices); LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal, LLVMValueRef *ConstantIndices, unsigned NumIndices); +LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, + unsigned NumIndices); LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstSExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstZExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); @@ -2037,6 +2168,14 @@ void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class); LLVMUnnamedAddr LLVMGetUnnamedAddress(LLVMValueRef Global); void LLVMSetUnnamedAddress(LLVMValueRef Global, LLVMUnnamedAddr UnnamedAddr); +/** + * Returns the "value type" of a global value. This differs from the formal + * type of a global value which is always a pointer type. + * + * @see llvm::GlobalValue::getValueType() + */ +LLVMTypeRef LLVMGlobalGetValueType(LLVMValueRef Global); + /** Deprecated: Use LLVMGetUnnamedAddress instead. */ LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global); /** Deprecated: Use LLVMSetUnnamedAddress instead. */ @@ -2067,6 +2206,58 @@ unsigned LLVMGetAlignment(LLVMValueRef V); */ void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes); +/** + * Sets a metadata attachment, erasing the existing metadata attachment if + * it already exists for the given kind. + * + * @see llvm::GlobalObject::setMetadata() + */ +void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD); + +/** + * Erases a metadata attachment of the given kind if it exists. + * + * @see llvm::GlobalObject::eraseMetadata() + */ +void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind); + +/** + * Removes all metadata attachments from this value. + * + * @see llvm::GlobalObject::clearMetadata() + */ +void LLVMGlobalClearMetadata(LLVMValueRef Global); + +/** + * Retrieves an array of metadata entries representing the metadata attached to + * this value. The caller is responsible for freeing this array by calling + * \c LLVMDisposeValueMetadataEntries. + * + * @see llvm::GlobalObject::getAllMetadata() + */ +LLVMValueMetadataEntry *LLVMGlobalCopyAllMetadata(LLVMValueRef Value, + size_t *NumEntries); + +/** + * Destroys value metadata entries. + */ +void LLVMDisposeValueMetadataEntries(LLVMValueMetadataEntry *Entries); + +/** + * Returns the kind of a value metadata entry at a specific index. + */ +unsigned LLVMValueMetadataEntriesGetKind(LLVMValueMetadataEntry *Entries, + unsigned Index); + +/** + * Returns the underlying metadata node of a value metadata entry at a + * specific index. + */ +LLVMMetadataRef +LLVMValueMetadataEntriesGetMetadata(LLVMValueMetadataEntry *Entries, + unsigned Index); + /** * @} */ @@ -2217,6 +2408,54 @@ void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn); */ unsigned LLVMGetIntrinsicID(LLVMValueRef Fn); +/** + * Create or insert the declaration of an intrinsic. For overloaded intrinsics, + * parameter types must be provided to uniquely identify an overload. + * + * @see llvm::Intrinsic::getDeclaration() + */ +LLVMValueRef LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod, + unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount); + +/** + * Retrieves the type of an intrinsic. For overloaded intrinsics, parameter + * types must be provided to uniquely identify an overload. + * + * @see llvm::Intrinsic::getType() + */ +LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID, + LLVMTypeRef *ParamTypes, size_t ParamCount); + +/** + * Retrieves the name of an intrinsic. + * + * @see llvm::Intrinsic::getName() + */ +const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength); + +/** + * Copies the name of an overloaded intrinsic identified by a given list of + * parameter types. + * + * Unlike LLVMIntrinsicGetName, the caller is responsible for freeing the + * returned string. + * + * @see llvm::Intrinsic::getName() + */ +const char *LLVMIntrinsicCopyOverloadedName(unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount, + size_t *NameLength); + +/** + * Obtain if the intrinsic identified by the given ID is overloaded. + * + * @see llvm::Intrinsic::isOverloaded() + */ +LLVMBool LLVMIntrinsicIsOverloaded(unsigned ID); + /** * Obtain the calling function of a function. * @@ -2514,7 +2753,7 @@ LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB); * If the basic block does not have a terminator (it is not well-formed * if it doesn't), then NULL is returned. * - * The returned LLVMValueRef corresponds to a llvm::TerminatorInst. + * The returned LLVMValueRef corresponds to an llvm::Instruction. * * @see llvm::BasicBlock::getTerminator() */ @@ -2572,6 +2811,14 @@ LLVMBasicBlockRef LLVMGetPreviousBasicBlock(LLVMBasicBlockRef BB); */ LLVMBasicBlockRef LLVMGetEntryBasicBlock(LLVMValueRef Fn); +/** + * Create a new basic block without inserting it into a function. + * + * @see llvm::BasicBlock::Create() + */ +LLVMBasicBlockRef LLVMCreateBasicBlockInContext(LLVMContextRef C, + const char *Name); + /** * Append a basic block to the end of a function. * @@ -2694,6 +2941,16 @@ LLVMValueRef LLVMGetMetadata(LLVMValueRef Val, unsigned KindID); */ void LLVMSetMetadata(LLVMValueRef Val, unsigned KindID, LLVMValueRef Node); +/** + * Returns the metadata associated with an instruction value, but filters out + * all the debug locations. + * + * @see llvm::Instruction::getAllMetadataOtherThanDebugLoc() + */ +LLVMValueMetadataEntry * +LLVMInstructionGetAllMetadataOtherThanDebugLoc(LLVMValueRef Instr, + size_t *NumEntries); + /** * Obtain the basic block to which an instruction belongs. * @@ -2776,6 +3033,15 @@ LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst); */ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst); +/** + * Determine whether an instruction is a terminator. This routine is named to + * be compatible with historical functions that did this by querying the + * underlying C++ type. + * + * @see llvm::Instruction::isTerminator() + */ +LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst); + /** * @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations * @@ -2838,6 +3104,13 @@ void LLVMRemoveCallSiteEnumAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, void LLVMRemoveCallSiteStringAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, const char *K, unsigned KLen); +/** + * Obtain the function type called by this instruction. + * + * @see llvm::CallBase::getFunctionType() + */ +LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef C); + /** * Obtain the pointer to the function invoked by this instruction. * @@ -2916,8 +3189,8 @@ void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B); /** * @defgroup LLVMCCoreValueInstructionTerminator Terminators * - * Functions in this group only apply to instructions that map to - * llvm::TerminatorInst instances. + * Functions in this group only apply to instructions for which + * LLVMIsATerminatorInst returns true. * * @{ */ @@ -2925,21 +3198,21 @@ void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B); /** * Return the number of successors that this terminator has. * - * @see llvm::TerminatorInst::getNumSuccessors + * @see llvm::Instruction::getNumSuccessors */ unsigned LLVMGetNumSuccessors(LLVMValueRef Term); /** * Return the specified successor. * - * @see llvm::TerminatorInst::getSuccessor + * @see llvm::Instruction::getSuccessor */ LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i); /** * Update the specified successor to point at the provided block. * - * @see llvm::TerminatorInst::setSuccessor + * @see llvm::Instruction::setSuccessor */ void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block); @@ -3130,10 +3403,16 @@ LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V, LLVMBasicBlockRef Else, unsigned NumCases); LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr, unsigned NumDests); +// LLVMBuildInvoke is deprecated in favor of LLVMBuildInvoke2, in preparation +// for opaque pointer types. LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, const char *Name); +LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, + const char *Name); LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); /* Exception Handling */ @@ -3290,13 +3569,48 @@ LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name); LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Val, const char *Name); + +/** + * Creates and inserts a memset to the specified pointer and the + * specified value. + * + * @see llvm::IRRBuilder::CreateMemSet() + */ +LLVMValueRef LLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, + LLVMValueRef Val, LLVMValueRef Len, + unsigned Align); +/** + * Creates and inserts a memcpy between the specified pointers. + * + * @see llvm::IRRBuilder::CreateMemCpy() + */ +LLVMValueRef LLVMBuildMemCpy(LLVMBuilderRef B, + LLVMValueRef Dst, unsigned DstAlign, + LLVMValueRef Src, unsigned SrcAlign, + LLVMValueRef Size); +/** + * Creates and inserts a memmove between the specified pointers. + * + * @see llvm::IRRBuilder::CreateMemMove() + */ +LLVMValueRef LLVMBuildMemMove(LLVMBuilderRef B, + LLVMValueRef Dst, unsigned DstAlign, + LLVMValueRef Src, unsigned SrcAlign, + LLVMValueRef Size); + LLVMValueRef LLVMBuildAlloca(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); LLVMValueRef LLVMBuildArrayAlloca(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Val, const char *Name); LLVMValueRef LLVMBuildFree(LLVMBuilderRef, LLVMValueRef PointerVal); +// LLVMBuildLoad is deprecated in favor of LLVMBuildLoad2, in preparation for +// opaque pointer types. LLVMValueRef LLVMBuildLoad(LLVMBuilderRef, LLVMValueRef PointerVal, const char *Name); +LLVMValueRef LLVMBuildLoad2(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef PointerVal, const char *Name); LLVMValueRef LLVMBuildStore(LLVMBuilderRef, LLVMValueRef Val, LLVMValueRef Ptr); +// LLVMBuildGEP, LLVMBuildInBoundsGEP, and LLVMBuildStructGEP are deprecated in +// favor of LLVMBuild*GEP2, in preparation for opaque pointer types. LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer, LLVMValueRef *Indices, unsigned NumIndices, const char *Name); @@ -3305,6 +3619,15 @@ LLVMValueRef LLVMBuildInBoundsGEP(LLVMBuilderRef B, LLVMValueRef Pointer, const char *Name); LLVMValueRef LLVMBuildStructGEP(LLVMBuilderRef B, LLVMValueRef Pointer, unsigned Idx, const char *Name); +LLVMValueRef LLVMBuildGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef Pointer, LLVMValueRef *Indices, + unsigned NumIndices, const char *Name); +LLVMValueRef LLVMBuildInBoundsGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef Pointer, LLVMValueRef *Indices, + unsigned NumIndices, const char *Name); +LLVMValueRef LLVMBuildStructGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef Pointer, unsigned Idx, + const char *Name); LLVMValueRef LLVMBuildGlobalString(LLVMBuilderRef B, const char *Str, const char *Name); LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str, @@ -3351,11 +3674,16 @@ LLVMValueRef LLVMBuildCast(LLVMBuilderRef B, LLVMOpcode Op, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildPointerCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); -LLVMValueRef LLVMBuildIntCast(LLVMBuilderRef, LLVMValueRef Val, /*Signed cast!*/ - LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildIntCast2(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, LLVMBool IsSigned, + const char *Name); LLVMValueRef LLVMBuildFPCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); +/** Deprecated: This cast is always signed. Use LLVMBuildIntCast2 instead. */ +LLVMValueRef LLVMBuildIntCast(LLVMBuilderRef, LLVMValueRef Val, /*Signed cast!*/ + LLVMTypeRef DestTy, const char *Name); + /* Comparisons */ LLVMValueRef LLVMBuildICmp(LLVMBuilderRef, LLVMIntPredicate Op, LLVMValueRef LHS, LLVMValueRef RHS, @@ -3366,9 +3694,14 @@ LLVMValueRef LLVMBuildFCmp(LLVMBuilderRef, LLVMRealPredicate Op, /* Miscellaneous instructions */ LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +// LLVMBuildCall is deprecated in favor of LLVMBuildCall2, in preparation for +// opaque pointer types. LLVMValueRef LLVMBuildCall(LLVMBuilderRef, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, const char *Name); +LLVMValueRef LLVMBuildCall2(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If, LLVMValueRef Then, LLVMValueRef Else, const char *Name); diff --git a/contrib/llvm/include/llvm-c/DebugInfo.h b/contrib/llvm/include/llvm-c/DebugInfo.h index cee6755f187..87a72034b0e 100644 --- a/contrib/llvm/include/llvm-c/DebugInfo.h +++ b/contrib/llvm/include/llvm-c/DebugInfo.h @@ -54,9 +54,12 @@ typedef enum { LLVMDIFlagMainSubprogram = 1 << 21, LLVMDIFlagTypePassByValue = 1 << 22, LLVMDIFlagTypePassByReference = 1 << 23, - LLVMDIFlagFixedEnum = 1 << 24, + LLVMDIFlagEnumClass = 1 << 24, + LLVMDIFlagFixedEnum = LLVMDIFlagEnumClass, // Deprecated. LLVMDIFlagThunk = 1 << 25, LLVMDIFlagTrivial = 1 << 26, + LLVMDIFlagBigEndian = 1 << 27, + LLVMDIFlagLittleEndian = 1 << 28, LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5), LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected | LLVMDIFlagPublic, @@ -124,6 +127,44 @@ typedef enum { LLVMDWARFEmissionLineTablesOnly } LLVMDWARFEmissionKind; +/** + * The kind of metadata nodes. + */ +enum { + LLVMMDStringMetadataKind, + LLVMConstantAsMetadataMetadataKind, + LLVMLocalAsMetadataMetadataKind, + LLVMDistinctMDOperandPlaceholderMetadataKind, + LLVMMDTupleMetadataKind, + LLVMDILocationMetadataKind, + LLVMDIExpressionMetadataKind, + LLVMDIGlobalVariableExpressionMetadataKind, + LLVMGenericDINodeMetadataKind, + LLVMDISubrangeMetadataKind, + LLVMDIEnumeratorMetadataKind, + LLVMDIBasicTypeMetadataKind, + LLVMDIDerivedTypeMetadataKind, + LLVMDICompositeTypeMetadataKind, + LLVMDISubroutineTypeMetadataKind, + LLVMDIFileMetadataKind, + LLVMDICompileUnitMetadataKind, + LLVMDISubprogramMetadataKind, + LLVMDILexicalBlockMetadataKind, + LLVMDILexicalBlockFileMetadataKind, + LLVMDINamespaceMetadataKind, + LLVMDIModuleMetadataKind, + LLVMDITemplateTypeParameterMetadataKind, + LLVMDITemplateValueParameterMetadataKind, + LLVMDIGlobalVariableMetadataKind, + LLVMDILocalVariableMetadataKind, + LLVMDILabelMetadataKind, + LLVMDIObjCPropertyMetadataKind, + LLVMDIImportedEntityMetadataKind, + LLVMDIMacroMetadataKind, + LLVMDIMacroFileMetadataKind +}; +typedef unsigned LLVMMetadataKind; + /** * An LLVM DWARF type encoding. */ @@ -531,11 +572,13 @@ LLVMDIBuilderCreateUnspecifiedType(LLVMDIBuilderRef Builder, const char *Name, * \param NameLen Length of type name. * \param SizeInBits Size of the type. * \param Encoding DWARF encoding code, e.g. \c LLVMDWARFTypeEncoding_float. + * \param Flags Flags to encode optional attribute like endianity */ LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name, size_t NameLen, uint64_t SizeInBits, - LLVMDWARFTypeEncoding Encoding); + LLVMDWARFTypeEncoding Encoding, + LLVMDIFlags Flags); /** * Create debugging information entry for a pointer. @@ -965,21 +1008,15 @@ LLVMDIBuilderCreateConstantValueExpression(LLVMDIBuilderRef Builder, * \param Expr The location of the global relative to the attached * GlobalVariable. * \param Decl Reference to the corresponding declaration. + * variables. * \param AlignInBits Variable alignment(or 0 if no alignment attr was * specified) */ -LLVMMetadataRef -LLVMDIBuilderCreateGlobalVariableExpression(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *Linkage, size_t LinkLen, - LLVMMetadataRef File, - unsigned LineNo, - LLVMMetadataRef Ty, - LLVMBool LocalToUnit, - LLVMMetadataRef Expr, - LLVMMetadataRef Decl, - uint32_t AlignInBits); +LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Expr, LLVMMetadataRef Decl, uint32_t AlignInBits); /** * Create a new temporary \c MDNode. Suitable for use in constructing cyclic * \c MDNode structures. A temporary \c MDNode is not uniqued, may be RAUW'd, @@ -1025,17 +1062,11 @@ void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef TempTargetMetadata, * \param AlignInBits Variable alignment(or 0 if no alignment attr was * specified) */ -LLVMMetadataRef -LLVMDIBuilderCreateTempGlobalVariableFwdDecl(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *Linkage, size_t LnkLen, - LLVMMetadataRef File, - unsigned LineNo, - LLVMMetadataRef Ty, - LLVMBool LocalToUnit, - LLVMMetadataRef Decl, - uint32_t AlignInBits); +LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LnkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Decl, uint32_t AlignInBits); /** * Insert a new llvm.dbg.declare intrinsic call before the given instruction. @@ -1149,6 +1180,13 @@ LLVMMetadataRef LLVMGetSubprogram(LLVMValueRef Func); */ void LLVMSetSubprogram(LLVMValueRef Func, LLVMMetadataRef SP); +/** + * Obtain the enumerated type of a Metadata instance. + * + * @see llvm::Metadata::getMetadataID() + */ +LLVMMetadataKind LLVMGetMetadataKind(LLVMMetadataRef Metadata); + #ifdef __cplusplus } /* end extern "C" */ #endif diff --git a/contrib/llvm/include/llvm-c/Error.h b/contrib/llvm/include/llvm-c/Error.h new file mode 100644 index 00000000000..71e84661222 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Error.h @@ -0,0 +1,69 @@ +/*===------- llvm-c/Error.h - llvm::Error class C Interface -------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to LLVM's Error class. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ERROR_H +#define LLVM_C_ERROR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LLVMErrorSuccess 0 + +/** + * Opaque reference to an error instance. Null serves as the 'success' value. + */ +typedef struct LLVMOpaqueError *LLVMErrorRef; + +/** + * Error type identifier. + */ +typedef const void *LLVMErrorTypeId; + +/** + * Returns the type id for the given error instance, which must be a failure + * value (i.e. non-null). + */ +LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err); + +/** + * Dispose of the given error without handling it. This operation consumes the + * error, and the given LLVMErrorRef value is not usable once this call returns. + * Note: This method *only* needs to be called if the error is not being passed + * to some other consuming operation, e.g. LLVMGetErrorMessage. + */ +void LLVMConsumeError(LLVMErrorRef Err); + +/** + * Returns the given string's error message. This operation consumes the error, + * and the given LLVMErrorRef value is not usable once this call returns. + * The caller is responsible for disposing of the string by calling + * LLVMDisposeErrorMessage. + */ +char *LLVMGetErrorMessage(LLVMErrorRef Err); + +/** + * Dispose of the given error message. + */ +void LLVMDisposeErrorMessage(char *ErrMsg); + +/** + * Returns the type id for llvm StringError. + */ +LLVMErrorTypeId LLVMGetStringErrorTypeId(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/llvm/include/llvm-c/ExecutionEngine.h b/contrib/llvm/include/llvm-c/ExecutionEngine.h index 49ae6fee45f..e8ebef9ab15 100644 --- a/contrib/llvm/include/llvm-c/ExecutionEngine.h +++ b/contrib/llvm/include/llvm-c/ExecutionEngine.h @@ -186,7 +186,7 @@ void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); LLVMJITEventListenerRef LLVMCreateGDBRegistrationListener(void); LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void); -LLVMJITEventListenerRef LLVMCreateOprofileJITEventListener(void); +LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void); LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void); /** diff --git a/contrib/llvm/include/llvm-c/OptRemarks.h b/contrib/llvm/include/llvm-c/OptRemarks.h new file mode 100644 index 00000000000..6a90394e711 --- /dev/null +++ b/contrib/llvm/include/llvm-c/OptRemarks.h @@ -0,0 +1,204 @@ +/*===-- llvm-c/OptRemarks.h - OptRemarks Public 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 provides a public interface to an opt-remark library. *| +|* LLVM provides an implementation of this interface. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_OPT_REMARKS_H +#define LLVM_C_OPT_REMARKS_H + +#include "llvm-c/Core.h" +#include "llvm-c/Types.h" +#ifdef __cplusplus +#include +extern "C" { +#else +#include +#endif /* !defined(__cplusplus) */ + +/** + * @defgroup LLVMCOPTREMARKS OptRemarks + * @ingroup LLVMC + * + * @{ + */ + +#define OPT_REMARKS_API_VERSION 0 + +/** + * String containing a buffer and a length. The buffer is not guaranteed to be + * zero-terminated. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +typedef struct { + const char *Str; + uint32_t Len; +} LLVMOptRemarkStringRef; + +/** + * DebugLoc containing File, Line and Column. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +typedef struct { + // File: + LLVMOptRemarkStringRef SourceFile; + // Line: + uint32_t SourceLineNumber; + // Column: + uint32_t SourceColumnNumber; +} LLVMOptRemarkDebugLoc; + +/** + * Element of the "Args" list. The key might give more information about what + * are the semantics of the value, e.g. "Callee" will tell you that the value + * is a symbol that names a function. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +typedef struct { + // e.g. "Callee" + LLVMOptRemarkStringRef Key; + // e.g. "malloc" + LLVMOptRemarkStringRef Value; + + // "DebugLoc": Optional + LLVMOptRemarkDebugLoc DebugLoc; +} LLVMOptRemarkArg; + +/** + * One remark entry. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +typedef struct { + // e.g. !Missed, !Passed + LLVMOptRemarkStringRef RemarkType; + // "Pass": Required + LLVMOptRemarkStringRef PassName; + // "Name": Required + LLVMOptRemarkStringRef RemarkName; + // "Function": Required + LLVMOptRemarkStringRef FunctionName; + + // "DebugLoc": Optional + LLVMOptRemarkDebugLoc DebugLoc; + // "Hotness": Optional + uint32_t Hotness; + // "Args": Optional. It is an array of `num_args` elements. + uint32_t NumArgs; + LLVMOptRemarkArg *Args; +} LLVMOptRemarkEntry; + +typedef struct LLVMOptRemarkOpaqueParser *LLVMOptRemarkParserRef; + +/** + * Creates a remark parser that can be used to read and parse the buffer located + * in \p Buf of size \p Size. + * + * \p Buf cannot be NULL. + * + * This function should be paired with LLVMOptRemarkParserDispose() to avoid + * leaking resources. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +extern LLVMOptRemarkParserRef LLVMOptRemarkParserCreate(const void *Buf, + uint64_t Size); + +/** + * Returns the next remark in the file. + * + * The value pointed to by the return value is invalidated by the next call to + * LLVMOptRemarkParserGetNext(). + * + * If the parser reaches the end of the buffer, the return value will be NULL. + * + * In the case of an error, the return value will be NULL, and: + * + * 1) LLVMOptRemarkParserHasError() will return `1`. + * + * 2) LLVMOptRemarkParserGetErrorMessage() will return a descriptive error + * message. + * + * An error may occur if: + * + * 1) An argument is invalid. + * + * 2) There is a YAML parsing error. This type of error aborts parsing + * immediately and returns `1`. It can occur on malformed YAML. + * + * 3) Remark parsing error. If this type of error occurs, the parser won't call + * the handler and will continue to the next one. It can occur on malformed + * remarks, like missing or extra fields in the file. + * + * Here is a quick example of the usage: + * + * ``` + * LLVMOptRemarkParserRef Parser = LLVMOptRemarkParserCreate(Buf, Size); + * LLVMOptRemarkEntry *Remark = NULL; + * while ((Remark == LLVMOptRemarkParserGetNext(Parser))) { + * // use Remark + * } + * bool HasError = LLVMOptRemarkParserHasError(Parser); + * LLVMOptRemarkParserDispose(Parser); + * ``` + * + * \since OPT_REMARKS_API_VERSION=0 + */ +extern LLVMOptRemarkEntry * +LLVMOptRemarkParserGetNext(LLVMOptRemarkParserRef Parser); + +/** + * Returns `1` if the parser encountered an error while parsing the buffer. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +extern LLVMBool LLVMOptRemarkParserHasError(LLVMOptRemarkParserRef Parser); + +/** + * Returns a null-terminated string containing an error message. + * + * In case of no error, the result is `NULL`. + * + * The memory of the string is bound to the lifetime of \p Parser. If + * LLVMOptRemarkParserDispose() is called, the memory of the string will be + * released. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +extern const char * +LLVMOptRemarkParserGetErrorMessage(LLVMOptRemarkParserRef Parser); + +/** + * Releases all the resources used by \p Parser. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +extern void LLVMOptRemarkParserDispose(LLVMOptRemarkParserRef Parser); + +/** + * Returns the version of the opt-remarks dylib. + * + * \since OPT_REMARKS_API_VERSION=0 + */ +extern uint32_t LLVMOptRemarkVersion(void); + +/** + * @} // endgoup LLVMCOPTREMARKS + */ + +#ifdef __cplusplus +} +#endif /* !defined(__cplusplus) */ + +#endif /* LLVM_C_OPT_REMARKS_H */ diff --git a/contrib/llvm/include/llvm-c/OrcBindings.h b/contrib/llvm/include/llvm-c/OrcBindings.h index 9497f0d4077..570db87fee9 100644 --- a/contrib/llvm/include/llvm-c/OrcBindings.h +++ b/contrib/llvm/include/llvm-c/OrcBindings.h @@ -22,6 +22,7 @@ #ifndef LLVM_C_ORCBINDINGS_H #define LLVM_C_ORCBINDINGS_H +#include "llvm-c/Error.h" #include "llvm-c/Object.h" #include "llvm-c/TargetMachine.h" @@ -36,8 +37,6 @@ typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx); typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack, void *CallbackCtx); -typedef enum { LLVMOrcErrSuccess = 0, LLVMOrcErrGeneric } LLVMOrcErrorCode; - /** * Create an ORC JIT stack. * @@ -72,43 +71,41 @@ void LLVMOrcDisposeMangledSymbol(char *MangledSymbol); /** * Create a lazy compile callback. */ -LLVMOrcErrorCode -LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack, - LLVMOrcTargetAddress *RetAddr, - LLVMOrcLazyCompileCallbackFn Callback, - void *CallbackCtx); +LLVMErrorRef LLVMOrcCreateLazyCompileCallback( + LLVMOrcJITStackRef JITStack, LLVMOrcTargetAddress *RetAddr, + LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx); /** * Create a named indirect call stub. */ -LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack, - const char *StubName, - LLVMOrcTargetAddress InitAddr); +LLVMErrorRef LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack, + const char *StubName, + LLVMOrcTargetAddress InitAddr); /** * Set the pointer for the given indirect stub. */ -LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, - const char *StubName, - LLVMOrcTargetAddress NewAddr); +LLVMErrorRef LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, + const char *StubName, + LLVMOrcTargetAddress NewAddr); /** * Add module to be eagerly compiled. */ -LLVMOrcErrorCode -LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod, - LLVMOrcSymbolResolverFn SymbolResolver, - void *SymbolResolverCtx); +LLVMErrorRef LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMModuleRef Mod, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx); /** * Add module to be lazily compiled one function at a time. */ -LLVMOrcErrorCode -LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod, - LLVMOrcSymbolResolverFn SymbolResolver, - void *SymbolResolverCtx); +LLVMErrorRef LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMModuleRef Mod, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx); /** * Add an object file. @@ -118,11 +115,11 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, * Clients should *not* dispose of the 'Obj' argument: the JIT will manage it * from this call onwards. */ -LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, - LLVMMemoryBufferRef Obj, - LLVMOrcSymbolResolverFn SymbolResolver, - void *SymbolResolverCtx); +LLVMErrorRef LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMMemoryBufferRef Obj, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx); /** * Remove a module set from the JIT. @@ -130,29 +127,29 @@ LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, * This works for all modules that can be added via OrcAdd*, including object * files. */ -LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle H); +LLVMErrorRef LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle H); /** * Get symbol address from JIT instance. */ -LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, - LLVMOrcTargetAddress *RetAddr, - const char *SymbolName); +LLVMErrorRef LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, + const char *SymbolName); /** * Get symbol address from JIT instance, searching only the specified * handle. */ -LLVMOrcErrorCode LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack, - LLVMOrcTargetAddress *RetAddr, - LLVMOrcModuleHandle H, - const char *SymbolName); +LLVMErrorRef LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, + LLVMOrcModuleHandle H, + const char *SymbolName); /** * Dispose of an ORC JIT stack. */ -LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); +LLVMErrorRef LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); /** * Register a JIT Event Listener. diff --git a/contrib/llvm/include/llvm-c/TargetMachine.h b/contrib/llvm/include/llvm-c/TargetMachine.h index 7f672b5d10d..c06e9edc9aa 100644 --- a/contrib/llvm/include/llvm-c/TargetMachine.h +++ b/contrib/llvm/include/llvm-c/TargetMachine.h @@ -39,12 +39,16 @@ typedef enum { LLVMRelocDefault, LLVMRelocStatic, LLVMRelocPIC, - LLVMRelocDynamicNoPic + LLVMRelocDynamicNoPic, + LLVMRelocROPI, + LLVMRelocRWPI, + LLVMRelocROPI_RWPI } LLVMRelocMode; typedef enum { LLVMCodeModelDefault, LLVMCodeModelJITDefault, + LLVMCodeModelTiny, LLVMCodeModelSmall, LLVMCodeModelKernel, LLVMCodeModelMedium, diff --git a/contrib/llvm/include/llvm-c/Transforms/AggressiveInstCombine.h b/contrib/llvm/include/llvm-c/Transforms/AggressiveInstCombine.h new file mode 100644 index 00000000000..8756a22e917 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Transforms/AggressiveInstCombine.h @@ -0,0 +1,43 @@ +/*===-- AggressiveInstCombine.h ---------------------------------*- 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 libLLVMAggressiveInstCombine.a, *| +|* which combines instructions to form fewer, simple IR instructions. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_AGGRESSIVEINSTCOMBINE_H +#define LLVM_C_TRANSFORMS_AGGRESSIVEINSTCOMBINE_H + +#include "llvm-c/Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup LLVMCTransformsAggressiveInstCombine Aggressive Instruction Combining transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createAggressiveInstCombinerPass function. */ +void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif + diff --git a/contrib/llvm/include/llvm-c/Transforms/Coroutines.h b/contrib/llvm/include/llvm-c/Transforms/Coroutines.h new file mode 100644 index 00000000000..827e30fb2d7 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Transforms/Coroutines.h @@ -0,0 +1,55 @@ +/*===-- Coroutines.h - Coroutines Library 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 libLLVMCoroutines.a, which *| +|* implements various scalar transformations of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_COROUTINES_H +#define LLVM_C_TRANSFORMS_COROUTINES_H + +#include "llvm-c/Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup LLVMCTransformsCoroutines Coroutine transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createCoroEarlyPass function. */ +void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM); + +/** See llvm::createCoroSplitPass function. */ +void LLVMAddCoroSplitPass(LLVMPassManagerRef PM); + +/** See llvm::createCoroElidePass function. */ +void LLVMAddCoroElidePass(LLVMPassManagerRef PM); + +/** See llvm::createCoroCleanupPass function. */ +void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h index f55cdce86be..3c3bb4eb9b8 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h @@ -35,9 +35,6 @@ extern "C" { /** See llvm::createAggressiveDCEPass function. */ void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); -/** See llvm::createAggressiveInstCombinerPass function. */ -void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM); - /** See llvm::createBitTrackingDCEPass function. */ void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM); @@ -95,6 +92,9 @@ void LLVMAddLoopUnrollAndJamPass(LLVMPassManagerRef PM); /** See llvm::createLoopUnswitchPass function. */ void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); +/** See llvm::createLowerAtomicPass function. */ +void LLVMAddLowerAtomicPass(LLVMPassManagerRef PM); + /** See llvm::createMemCpyOptPass function. */ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); @@ -153,6 +153,9 @@ void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM); /** See llvm::createBasicAliasAnalysisPass function */ void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); +/** See llvm::createUnifyFunctionExitNodesPass function */ +void LLVMAddUnifyFunctionExitNodesPass(LLVMPassManagerRef PM); + /** * @} */ diff --git a/contrib/llvm/include/llvm-c/Types.h b/contrib/llvm/include/llvm-c/Types.h index 4a33542e86c..ce1acf3e042 100644 --- a/contrib/llvm/include/llvm-c/Types.h +++ b/contrib/llvm/include/llvm-c/Types.h @@ -89,6 +89,20 @@ typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef; */ typedef struct LLVMOpaqueMetadata *LLVMMetadataRef; +/** + * Represents an LLVM Named Metadata Node. + * + * This models llvm::NamedMDNode. + */ +typedef struct LLVMOpaqueNamedMDNode *LLVMNamedMDNodeRef; + +/** + * Represents an entry in a Global Object's metadata attachments. + * + * This models std::pair + */ +typedef struct LLVMOpaqueValueMetadataEntry LLVMValueMetadataEntry; + /** * Represents an LLVM basic block builder. * diff --git a/contrib/llvm/include/llvm-c/lto.h b/contrib/llvm/include/llvm-c/lto.h index 1acd610f70a..090cd34af4e 100644 --- a/contrib/llvm/include/llvm-c/lto.h +++ b/contrib/llvm/include/llvm-c/lto.h @@ -44,7 +44,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 22 +#define LTO_API_VERSION 23 /** * \since prior to LTO_API_VERSION=3 @@ -827,6 +827,16 @@ extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg, extern void thinlto_codegen_set_cache_size_bytes(thinlto_code_gen_t cg, unsigned max_size_bytes); +/** + * Same as thinlto_codegen_set_cache_size_bytes, except the maximum size is in + * megabytes (2^20 bytes). + * + * \since LTO_API_VERSION=23 + */ +extern void +thinlto_codegen_set_cache_size_megabytes(thinlto_code_gen_t cg, + unsigned max_size_megabytes); + /** * Sets the maximum number of files in the cache directory. An unspecified * default value will be applied. A value of 0 will be ignored. diff --git a/contrib/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm/include/llvm/ADT/APFloat.h index 5c59af4c04b..c6fa5ad674f 100644 --- a/contrib/llvm/include/llvm/ADT/APFloat.h +++ b/contrib/llvm/include/llvm/ADT/APFloat.h @@ -870,13 +870,13 @@ public: /// Factory for NaN values. /// /// \param Negative - True iff the NaN generated should be negative. - /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// \param payload - The unspecified fill bits for creating the NaN, 0 by /// default. The value is truncated as necessary. static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, - unsigned type = 0) { - if (type) { - APInt fill(64, type); - return getQNaN(Sem, Negative, &fill); + uint64_t payload = 0) { + if (payload) { + APInt intPayload(64, payload); + return getQNaN(Sem, Negative, &intPayload); } else { return getQNaN(Sem, Negative, nullptr); } @@ -1243,6 +1243,32 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) { return (A.compare(B) == APFloat::cmpLessThan) ? B : A; } +/// Implements IEEE 754-2018 minimum semantics. Returns the smaller of 2 +/// arguments, propagating NaNs and treating -0 as less than +0. +LLVM_READONLY +inline APFloat minimum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return A; + if (B.isNaN()) + return B; + if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative())) + return A.isNegative() ? A : B; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE 754-2018 maximum semantics. Returns the larger of 2 +/// arguments, propagating NaNs and treating -0 as less than +0. +LLVM_READONLY +inline APFloat maximum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return A; + if (B.isNaN()) + return B; + if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative())) + return A.isNegative() ? B : A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + } // namespace llvm #undef APFLOAT_DISPATCH_ON_SEMANTICS diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index 6bf6b22fb01..6e106ff8bf5 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -31,6 +31,7 @@ class raw_ostream; template class SmallVectorImpl; template class ArrayRef; +template class Optional; class APInt; @@ -84,7 +85,7 @@ public: UP, }; - static const WordType WORD_MAX = ~WordType(0); + static const WordType WORDTYPE_MAX = ~WordType(0); private: /// This union is used to store the integer value. When the @@ -149,7 +150,7 @@ private: unsigned WordBits = ((BitWidth-1) % APINT_BITS_PER_WORD) + 1; // Mask out the high bits. - uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - WordBits); + uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits); if (isSingleWord()) U.VAL &= mask; else @@ -394,7 +395,7 @@ public: /// This checks to see if the value has all bits of the APInt are set or not. bool isAllOnesValue() const { if (isSingleWord()) - return U.VAL == WORD_MAX >> (APINT_BITS_PER_WORD - BitWidth); + return U.VAL == WORDTYPE_MAX >> (APINT_BITS_PER_WORD - BitWidth); return countTrailingOnesSlowCase() == BitWidth; } @@ -495,7 +496,7 @@ public: assert(numBits != 0 && "numBits must be non-zero"); assert(numBits <= BitWidth && "numBits out of range"); if (isSingleWord()) - return U.VAL == (WORD_MAX >> (APINT_BITS_PER_WORD - numBits)); + return U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits)); unsigned Ones = countTrailingOnesSlowCase(); return (numBits == Ones) && ((Ones + countLeadingZerosSlowCase()) == BitWidth); @@ -559,7 +560,7 @@ public: /// /// \returns the all-ones value for an APInt of the specified bit-width. static APInt getAllOnesValue(unsigned numBits) { - return APInt(numBits, WORD_MAX, true); + return APInt(numBits, WORDTYPE_MAX, true); } /// Get the '0' value. @@ -1104,6 +1105,12 @@ public: APInt sshl_ov(const APInt &Amt, bool &Overflow) const; APInt ushl_ov(const APInt &Amt, bool &Overflow) const; + // Operations that saturate + APInt sadd_sat(const APInt &RHS) const; + APInt uadd_sat(const APInt &RHS) const; + APInt ssub_sat(const APInt &RHS) const; + APInt usub_sat(const APInt &RHS) const; + /// Array-indexing support. /// /// \returns the bit value at bitPosition @@ -1382,7 +1389,7 @@ public: /// Set every bit to 1. void setAllBits() { if (isSingleWord()) - U.VAL = WORD_MAX; + U.VAL = WORDTYPE_MAX; else // Set all the bits in all the words. memset(U.pVal, -1, getNumWords() * APINT_WORD_SIZE); @@ -1394,7 +1401,7 @@ public: /// /// Set the given bit to 1 whose position is given as "bitPosition". void setBit(unsigned BitPosition) { - assert(BitPosition <= BitWidth && "BitPosition out of range"); + assert(BitPosition < BitWidth && "BitPosition out of range"); WordType Mask = maskBit(BitPosition); if (isSingleWord()) U.VAL |= Mask; @@ -1415,7 +1422,7 @@ public: if (loBit == hiBit) return; if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) { - uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit)); + uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit)); mask <<= loBit; if (isSingleWord()) U.VAL |= mask; @@ -1453,7 +1460,7 @@ public: /// /// Set the given bit to 0 whose position is given as "bitPosition". void clearBit(unsigned BitPosition) { - assert(BitPosition <= BitWidth && "BitPosition out of range"); + assert(BitPosition < BitWidth && "BitPosition out of range"); WordType Mask = ~maskBit(BitPosition); if (isSingleWord()) U.VAL &= Mask; @@ -1469,7 +1476,7 @@ public: /// Toggle every bit to its opposite value. void flipAllBits() { if (isSingleWord()) { - U.VAL ^= WORD_MAX; + U.VAL ^= WORDTYPE_MAX; clearUnusedBits(); } else { flipAllBitsSlowCase(); @@ -1758,7 +1765,7 @@ public: /// referencing 2 in a space where 2 does no exist. unsigned nearestLogBase2() const { // Special case when we have a bitwidth of 1. If VAL is 1, then we - // get 0. If VAL is 0, we get WORD_MAX which gets truncated to + // get 0. If VAL is 0, we get WORDTYPE_MAX which gets truncated to // UINT32_MAX. if (BitWidth == 1) return U.VAL - 1; @@ -2166,6 +2173,41 @@ APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM); /// Return A sign-divided by B, rounded by the given rounding mode. APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM); +/// Let q(n) = An^2 + Bn + C, and BW = bit width of the value range +/// (e.g. 32 for i32). +/// This function finds the smallest number n, such that +/// (a) n >= 0 and q(n) = 0, or +/// (b) n >= 1 and q(n-1) and q(n), when evaluated in the set of all +/// integers, belong to two different intervals [Rk, Rk+R), +/// where R = 2^BW, and k is an integer. +/// The idea here is to find when q(n) "overflows" 2^BW, while at the +/// same time "allowing" subtraction. In unsigned modulo arithmetic a +/// subtraction (treated as addition of negated numbers) would always +/// count as an overflow, but here we want to allow values to decrease +/// and increase as long as they are within the same interval. +/// Specifically, adding of two negative numbers should not cause an +/// overflow (as long as the magnitude does not exceed the bith width). +/// On the other hand, given a positive number, adding a negative +/// number to it can give a negative result, which would cause the +/// value to go from [-2^BW, 0) to [0, 2^BW). In that sense, zero is +/// treated as a special case of an overflow. +/// +/// This function returns None if after finding k that minimizes the +/// positive solution to q(n) = kR, both solutions are contained between +/// two consecutive integers. +/// +/// There are cases where q(n) > T, and q(n+1) < T (assuming evaluation +/// in arithmetic modulo 2^BW, and treating the values as signed) by the +/// virtue of *signed* overflow. This function will *not* find such an n, +/// however it may find a value of n satisfying the inequalities due to +/// an *unsigned* overflow (if the values are treated as unsigned). +/// To find a solution for a signed overflow, treat it as a problem of +/// finding an unsigned overflow with a range with of BW-1. +/// +/// The returned value may have a different bit width from the input +/// coefficients. +Optional SolveQuadraticEquationWrap(APInt A, APInt B, APInt C, + unsigned RangeWidth); } // End of APIntOps namespace // See friend declaration above. This additional declaration is required in diff --git a/contrib/llvm/include/llvm/ADT/Any.h b/contrib/llvm/include/llvm/ADT/Any.h index c64c3998754..7faa4c963d3 100644 --- a/contrib/llvm/include/llvm/ADT/Any.h +++ b/contrib/llvm/include/llvm/ADT/Any.h @@ -65,6 +65,16 @@ public: typename std::enable_if< llvm::conjunction< llvm::negation::type, Any>>, + // We also disable this overload when an `Any` object can be + // converted to the parameter type because in that case, this + // constructor may combine with that conversion during overload + // resolution for determining copy constructibility, and then + // when we try to determine copy constructibility below we may + // infinitely recurse. This is being evaluated by the standards + // committee as a potential DR in `std::any` as well, but we're + // going ahead and adopting it to work-around usage of `Any` with + // types that need to be implicitly convertible from an `Any`. + llvm::negation::type>>, std::is_copy_constructible::type>>::value, int>::type = 0> Any(T &&Value) { diff --git a/contrib/llvm/include/llvm/ADT/BitVector.h b/contrib/llvm/include/llvm/ADT/BitVector.h index 438c7d84c58..9ab1da7c691 100644 --- a/contrib/llvm/include/llvm/ADT/BitVector.h +++ b/contrib/llvm/include/llvm/ADT/BitVector.h @@ -503,6 +503,23 @@ public: return (*this)[Idx]; } + // Push single bit to end of vector. + void push_back(bool Val) { + unsigned OldSize = Size; + unsigned NewSize = Size + 1; + + // Resize, which will insert zeros. + // If we already fit then the unused bits will be already zero. + if (NewSize > getBitCapacity()) + resize(NewSize, false); + else + Size = NewSize; + + // If true, set single bit. + if (Val) + set(OldSize); + } + /// Test if any common bits are set. bool anyCommon(const BitVector &RHS) const { unsigned ThisWords = NumBitWords(size()); diff --git a/contrib/llvm/include/llvm/ADT/DenseMap.h b/contrib/llvm/include/llvm/ADT/DenseMap.h index ba60b7972a8..1f50502fff9 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMap.h +++ b/contrib/llvm/include/llvm/ADT/DenseMap.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,34 @@ namespace detail { // implementation without requiring two members. template struct DenseMapPair : public std::pair { + + // FIXME: Switch to inheriting constructors when we drop support for older + // clang versions. + // NOTE: This default constructor is declared with '{}' rather than + // '= default' to work around a separate bug in clang-3.8. This can + // also go when we switch to inheriting constructors. + DenseMapPair() {} + + DenseMapPair(const KeyT &Key, const ValueT &Value) + : std::pair(Key, Value) {} + + DenseMapPair(KeyT &&Key, ValueT &&Value) + : std::pair(std::move(Key), std::move(Value)) {} + + template + DenseMapPair(AltKeyT &&AltKey, AltValueT &&AltValue, + typename std::enable_if< + std::is_convertible::value && + std::is_convertible::value>::type * = 0) + : std::pair(std::forward(AltKey), + std::forward(AltValue)) {} + + template + DenseMapPair(AltPairT &&AltPair, + typename std::enable_if>::value>::type * = 0) + : std::pair(std::forward(AltPair)) {} + KeyT &getFirst() { return std::pair::first; } const KeyT &getFirst() const { return std::pair::first; } ValueT &getSecond() { return std::pair::second; } @@ -46,9 +75,10 @@ struct DenseMapPair : public std::pair { } // end namespace detail -template < - typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo, - typename Bucket = detail::DenseMapPair, bool IsConst = false> +template , + typename Bucket = llvm::detail::DenseMapPair, + bool IsConst = false> class DenseMapIterator; template ::value && isPodLike::value) - memcpy(getBuckets(), other.getBuckets(), + memcpy(reinterpret_cast(getBuckets()), other.getBuckets(), getNumBuckets() * sizeof(BucketT)); else for (size_t i = 0; i < getNumBuckets(); ++i) { @@ -639,9 +669,43 @@ public: } }; +/// Equality comparison for DenseMap. +/// +/// Iterates over elements of LHS confirming that each (key, value) pair in LHS +/// is also in RHS, and that no additional pairs are in RHS. +/// Equivalent to N calls to RHS.find and N value comparisons. Amortized +/// complexity is linear, worst case is O(N^2) (if every hash collides). +template +bool operator==( + const DenseMapBase &LHS, + const DenseMapBase &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (auto &KV : LHS) { + auto I = RHS.find(KV.first); + if (I == RHS.end() || I->second != KV.second) + return false; + } + + return true; +} + +/// Inequality comparison for DenseMap. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template +bool operator!=( + const DenseMapBase &LHS, + const DenseMapBase &RHS) { + return !(LHS == RHS); +} + template , - typename BucketT = detail::DenseMapPair> + typename BucketT = llvm::detail::DenseMapPair> class DenseMap : public DenseMapBase, KeyT, ValueT, KeyInfoT, BucketT> { friend class DenseMapBase; @@ -676,6 +740,11 @@ public: this->insert(I, E); } + DenseMap(std::initializer_list Vals) { + init(Vals.size()); + this->insert(Vals.begin(), Vals.end()); + } + ~DenseMap() { this->destroyAll(); operator delete(Buckets); @@ -798,7 +867,7 @@ private: template , - typename BucketT = detail::DenseMapPair> + typename BucketT = llvm::detail::DenseMapPair> class SmallDenseMap : public DenseMapBase< SmallDenseMap, KeyT, diff --git a/contrib/llvm/include/llvm/ADT/DenseSet.h b/contrib/llvm/include/llvm/ADT/DenseSet.h index b495e25dd5e..e85a38587e4 100644 --- a/contrib/llvm/include/llvm/ADT/DenseSet.h +++ b/contrib/llvm/include/llvm/ADT/DenseSet.h @@ -16,6 +16,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/type_traits.h" #include #include @@ -67,7 +68,7 @@ public: explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {} DenseSetImpl(std::initializer_list Elems) - : DenseSetImpl(Elems.size()) { + : DenseSetImpl(PowerOf2Ceil(Elems.size())) { insert(Elems.begin(), Elems.end()); } @@ -136,8 +137,8 @@ public: public: using difference_type = typename MapTy::const_iterator::difference_type; using value_type = ValueT; - using pointer = value_type *; - using reference = value_type &; + using pointer = const value_type *; + using reference = const value_type &; using iterator_category = std::forward_iterator_tag; ConstIterator() = default; @@ -214,6 +215,34 @@ public: } }; +/// Equality comparison for DenseSet. +/// +/// Iterates over elements of LHS confirming that each element is also a member +/// of RHS, and that RHS contains no additional values. +/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst +/// case is O(N^2) (if every hash collides). +template +bool operator==(const DenseSetImpl &LHS, + const DenseSetImpl &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (auto &E : LHS) + if (!RHS.count(E)) + return false; + + return true; +} + +/// Inequality comparison for DenseSet. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template +bool operator!=(const DenseSetImpl &LHS, + const DenseSetImpl &RHS) { + return !(LHS == RHS); +} + } // end namespace detail /// Implements a dense probed hash-table based set. diff --git a/contrib/llvm/include/llvm/ADT/GraphTraits.h b/contrib/llvm/include/llvm/ADT/GraphTraits.h index 27c647f4bbb..d39b50fdc48 100644 --- a/contrib/llvm/include/llvm/ADT/GraphTraits.h +++ b/contrib/llvm/include/llvm/ADT/GraphTraits.h @@ -25,6 +25,13 @@ namespace llvm { // GraphTraits - This class should be specialized by different graph types... // which is why the default version is empty. // +// This template evolved from supporting `BasicBlock` to also later supporting +// more complex types (e.g. CFG and DomTree). +// +// GraphTraits can be used to create a view over a graph interpreting it +// differently without requiring a copy of the original graph. This could +// be achieved by carrying more data in NodeRef. See LoopBodyTraits for one +// example. template struct GraphTraits { // Elements to provide: diff --git a/contrib/llvm/include/llvm/ADT/Hashing.h b/contrib/llvm/include/llvm/ADT/Hashing.h index 9f830baa424..9175c545b7c 100644 --- a/contrib/llvm/include/llvm/ADT/Hashing.h +++ b/contrib/llvm/include/llvm/ADT/Hashing.h @@ -133,7 +133,7 @@ hash_code hash_value(const std::basic_string &arg); /// undone. This makes it thread-hostile and very hard to use outside of /// immediately on start of a simple program designed for reproducible /// behavior. -void set_fixed_execution_hash_seed(size_t fixed_value); +void set_fixed_execution_hash_seed(uint64_t fixed_value); // All of the implementation details of actually computing the various hash @@ -316,9 +316,9 @@ struct hash_state { /// This variable can be set using the \see llvm::set_fixed_execution_seed /// function. See that function for details. Do not, under any circumstances, /// set or read this variable. -extern size_t fixed_seed_override; +extern uint64_t fixed_seed_override; -inline size_t get_execution_seed() { +inline uint64_t get_execution_seed() { // FIXME: This needs to be a per-execution seed. This is just a placeholder // implementation. Switching to a per-execution seed is likely to flush out // instability bugs and so will happen as its own commit. @@ -326,8 +326,7 @@ inline size_t get_execution_seed() { // However, if there is a fixed seed override set the first time this is // called, return that instead of the per-execution seed. const uint64_t seed_prime = 0xff51afd7ed558ccdULL; - static size_t seed = fixed_seed_override ? fixed_seed_override - : (size_t)seed_prime; + static uint64_t seed = fixed_seed_override ? fixed_seed_override : seed_prime; return seed; } @@ -402,7 +401,7 @@ bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, /// combining them, this (as an optimization) directly combines the integers. template hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { - const size_t seed = get_execution_seed(); + const uint64_t seed = get_execution_seed(); char buffer[64], *buffer_ptr = buffer; char *const buffer_end = std::end(buffer); while (first != last && store_and_advance(buffer_ptr, buffer_end, @@ -446,7 +445,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { template typename std::enable_if::value, hash_code>::type hash_combine_range_impl(ValueT *first, ValueT *last) { - const size_t seed = get_execution_seed(); + const uint64_t seed = get_execution_seed(); const char *s_begin = reinterpret_cast(first); const char *s_end = reinterpret_cast(last); const size_t length = std::distance(s_begin, s_end); @@ -496,7 +495,7 @@ namespace detail { struct hash_combine_recursive_helper { char buffer[64]; hash_state state; - const size_t seed; + const uint64_t seed; public: /// Construct a recursive hash combining helper. diff --git a/contrib/llvm/include/llvm/ADT/ImmutableList.h b/contrib/llvm/include/llvm/ADT/ImmutableList.h index 1f5e9813798..0541dc2566e 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableList.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableList.h @@ -31,8 +31,9 @@ class ImmutableListImpl : public FoldingSetNode { T Head; const ImmutableListImpl* Tail; - ImmutableListImpl(const T& head, const ImmutableListImpl* tail = nullptr) - : Head(head), Tail(tail) {} + template + ImmutableListImpl(ElemT &&head, const ImmutableListImpl *tail = nullptr) + : Head(std::forward(head)), Tail(tail) {} public: ImmutableListImpl(const ImmutableListImpl &) = delete; @@ -66,6 +67,9 @@ public: using value_type = T; using Factory = ImmutableListFactory; + static_assert(std::is_trivially_destructible::value, + "T must be trivially destructible!"); + private: const ImmutableListImpl* X; @@ -90,6 +94,9 @@ public: bool operator==(const iterator& I) const { return L == I.L; } bool operator!=(const iterator& I) const { return L != I.L; } const value_type& operator*() const { return L->getHead(); } + const typename std::remove_reference::type* operator->() const { + return &L->getHead(); + } ImmutableList getList() const { return L; } }; @@ -123,14 +130,14 @@ public: bool operator==(const ImmutableList& L) const { return isEqual(L); } /// getHead - Returns the head of the list. - const T& getHead() { + const T& getHead() const { assert(!isEmpty() && "Cannot get the head of an empty list."); return X->getHead(); } /// getTail - Returns the tail of the list, which is another (possibly empty) /// ImmutableList. - ImmutableList getTail() { + ImmutableList getTail() const { return X ? X->getTail() : nullptr; } @@ -166,7 +173,8 @@ public: if (ownsAllocator()) delete &getAllocator(); } - LLVM_NODISCARD ImmutableList concat(const T &Head, ImmutableList Tail) { + template + LLVM_NODISCARD ImmutableList concat(ElemT &&Head, ImmutableList Tail) { // Profile the new list to see if it already exists in our cache. FoldingSetNodeID ID; void* InsertPos; @@ -179,7 +187,7 @@ public: // The list does not exist in our cache. Create it. BumpPtrAllocator& A = getAllocator(); L = (ListTy*) A.Allocate(); - new (L) ListTy(Head, TailImpl); + new (L) ListTy(std::forward(Head), TailImpl); // Insert the new list into the cache. Cache.InsertNode(L, InsertPos); @@ -188,16 +196,24 @@ public: return L; } - LLVM_NODISCARD ImmutableList add(const T& D, ImmutableList L) { - return concat(D, L); + template + LLVM_NODISCARD ImmutableList add(ElemT &&Data, ImmutableList L) { + return concat(std::forward(Data), L); + } + + template + LLVM_NODISCARD ImmutableList emplace(ImmutableList Tail, + CtorArgs &&...Args) { + return concat(T(std::forward(Args)...), Tail); } ImmutableList getEmptyList() const { return ImmutableList(nullptr); } - ImmutableList create(const T& X) { - return Concat(X, getEmptyList()); + template + ImmutableList create(ElemT &&Data) { + return concat(std::forward(Data), getEmptyList()); } }; diff --git a/contrib/llvm/include/llvm/ADT/IntervalMap.h b/contrib/llvm/include/llvm/ADT/IntervalMap.h index f7136681121..2af61049e5a 100644 --- a/contrib/llvm/include/llvm/ADT/IntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/IntervalMap.h @@ -101,6 +101,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/bit.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/RecyclingAllocator.h" @@ -963,6 +964,7 @@ public: private: // The root data is either a RootLeaf or a RootBranchData instance. + LLVM_ALIGNAS(RootLeaf) LLVM_ALIGNAS(RootBranchData) AlignedCharArrayUnion data; // Tree height. @@ -977,15 +979,10 @@ private: // Allocator used for creating external nodes. Allocator &allocator; - /// dataAs - Represent data as a node type without breaking aliasing rules. + /// Represent data as a node type without breaking aliasing rules. template T &dataAs() const { - union { - const char *d; - T *t; - } u; - u.d = data.buffer; - return *u.t; + return *bit_cast(const_cast(data.buffer)); } const RootLeaf &rootLeaf() const { @@ -1137,6 +1134,19 @@ public: I.find(x); return I; } + + /// overlaps(a, b) - Return true if the intervals in this map overlap with the + /// interval [a;b]. + bool overlaps(KeyT a, KeyT b) { + assert(Traits::nonEmpty(a, b)); + const_iterator I = find(a); + if (!I.valid()) + return false; + // [a;b] and [x;y] overlap iff x<=b and a<=y. The find() call guarantees the + // second part (y = find(a).stop()), so it is sufficient to check the first + // one. + return !Traits::stopLess(b, I.start()); + } }; /// treeSafeLookup - Return the mapped value at x or NotFound, assuming a diff --git a/contrib/llvm/include/llvm/ADT/Optional.h b/contrib/llvm/include/llvm/ADT/Optional.h index 353e5d0ec9d..76937d632ae 100644 --- a/contrib/llvm/include/llvm/ADT/Optional.h +++ b/contrib/llvm/include/llvm/ADT/Optional.h @@ -29,7 +29,7 @@ namespace llvm { namespace optional_detail { /// Storage for any type. -template struct OptionalStorage { +template ::value> struct OptionalStorage { AlignedCharArrayUnion storage; bool hasVal = false; @@ -108,28 +108,10 @@ template struct OptionalStorage { } }; -#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this. -/// Storage for trivially copyable types only. -template struct OptionalStorage { - AlignedCharArrayUnion storage; - bool hasVal = false; - - OptionalStorage() = default; - - OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } - OptionalStorage &operator=(const T &y) { - *reinterpret_cast(storage.buffer) = y; - hasVal = true; - return *this; - } - - void reset() { hasVal = false; } -}; -#endif } // namespace optional_detail template class Optional { - optional_detail::OptionalStorage::value> Storage; + optional_detail::OptionalStorage Storage; public: using value_type = T; diff --git a/contrib/llvm/include/llvm/ADT/PointerIntPair.h b/contrib/llvm/include/llvm/ADT/PointerIntPair.h index 884d05155bf..6d1b53a90ad 100644 --- a/contrib/llvm/include/llvm/ADT/PointerIntPair.h +++ b/contrib/llvm/include/llvm/ADT/PointerIntPair.h @@ -42,6 +42,8 @@ template , typename Info = PointerIntPairInfo> class PointerIntPair { + // Used by MSVC visualizer and generally helpful for debugging/visualizing. + using InfoTy = Info; intptr_t Value = 0; public: diff --git a/contrib/llvm/include/llvm/ADT/PointerSumType.h b/contrib/llvm/include/llvm/ADT/PointerSumType.h index e37957160d9..a19e45a4621 100644 --- a/contrib/llvm/include/llvm/ADT/PointerSumType.h +++ b/contrib/llvm/include/llvm/ADT/PointerSumType.h @@ -10,6 +10,7 @@ #ifndef LLVM_ADT_POINTERSUMTYPE_H #define LLVM_ADT_POINTERSUMTYPE_H +#include "llvm/ADT/bit.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include @@ -58,56 +59,142 @@ template struct PointerSumTypeHelper; /// and may be desirable to set to a state that is particularly desirable to /// default construct. /// +/// Having a supported zero-valued tag also enables getting the address of a +/// pointer stored with that tag provided it is stored in its natural bit +/// representation. This works because in the case of a zero-valued tag, the +/// pointer's value is directly stored into this object and we can expose the +/// address of that internal storage. This is especially useful when building an +/// `ArrayRef` of a single pointer stored in a sum type. +/// /// There is no support for constructing or accessing with a dynamic tag as /// that would fundamentally violate the type safety provided by the sum type. template class PointerSumType { - uintptr_t Value = 0; - using HelperT = detail::PointerSumTypeHelper; + // We keep both the raw value and the min tag value's pointer in a union. When + // the minimum tag value is zero, this allows code below to cleanly expose the + // address of the zero-tag pointer instead of just the zero-tag pointer + // itself. This is especially useful when building `ArrayRef`s out of a single + // pointer. However, we have to carefully access the union due to the active + // member potentially changing. When we *store* a new value, we directly + // access the union to allow us to store using the obvious types. However, + // when we *read* a value, we copy the underlying storage out to avoid relying + // on one member or the other being active. + union StorageT { + // Ensure we get a null default constructed value. We don't use a member + // initializer because some compilers seem to not implement those correctly + // for a union. + StorageT() : Value(0) {} + + uintptr_t Value; + + typename HelperT::template Lookup::PointerT MinTagPointer; + }; + + StorageT Storage; + public: constexpr PointerSumType() = default; + /// A typed setter to a given tagged member of the sum type. + template + void set(typename HelperT::template Lookup::PointerT Pointer) { + void *V = HelperT::template Lookup::TraitsT::getAsVoidPointer(Pointer); + assert((reinterpret_cast(V) & HelperT::TagMask) == 0 && + "Pointer is insufficiently aligned to store the discriminant!"); + Storage.Value = reinterpret_cast(V) | N; + } + /// A typed constructor for a specific tagged member of the sum type. template static PointerSumType create(typename HelperT::template Lookup::PointerT Pointer) { PointerSumType Result; - void *V = HelperT::template Lookup::TraitsT::getAsVoidPointer(Pointer); - assert((reinterpret_cast(V) & HelperT::TagMask) == 0 && - "Pointer is insufficiently aligned to store the discriminant!"); - Result.Value = reinterpret_cast(V) | N; + Result.set(Pointer); return Result; } - TagT getTag() const { return static_cast(Value & HelperT::TagMask); } + /// Clear the value to null with the min tag type. + void clear() { set(nullptr); } + + TagT getTag() const { + return static_cast(getOpaqueValue() & HelperT::TagMask); + } template bool is() const { return N == getTag(); } template typename HelperT::template Lookup::PointerT get() const { - void *P = is() ? getImpl() : nullptr; + void *P = is() ? getVoidPtr() : nullptr; return HelperT::template Lookup::TraitsT::getFromVoidPointer(P); } template typename HelperT::template Lookup::PointerT cast() const { assert(is() && "This instance has a different active member."); - return HelperT::template Lookup::TraitsT::getFromVoidPointer(getImpl()); + return HelperT::template Lookup::TraitsT::getFromVoidPointer( + getVoidPtr()); } - explicit operator bool() const { return Value & HelperT::PointerMask; } - bool operator==(const PointerSumType &R) const { return Value == R.Value; } - bool operator!=(const PointerSumType &R) const { return Value != R.Value; } - bool operator<(const PointerSumType &R) const { return Value < R.Value; } - bool operator>(const PointerSumType &R) const { return Value > R.Value; } - bool operator<=(const PointerSumType &R) const { return Value <= R.Value; } - bool operator>=(const PointerSumType &R) const { return Value >= R.Value; } + /// If the tag is zero and the pointer's value isn't changed when being + /// stored, get the address of the stored value type-punned to the zero-tag's + /// pointer type. + typename HelperT::template Lookup::PointerT const * + getAddrOfZeroTagPointer() const { + return const_cast(this)->getAddrOfZeroTagPointer(); + } - uintptr_t getOpaqueValue() const { return Value; } + /// If the tag is zero and the pointer's value isn't changed when being + /// stored, get the address of the stored value type-punned to the zero-tag's + /// pointer type. + typename HelperT::template Lookup::PointerT * + getAddrOfZeroTagPointer() { + static_assert(HelperT::MinTag == 0, "Non-zero minimum tag value!"); + assert(is() && "The active tag is not zero!"); + // Store the initial value of the pointer when read out of our storage. + auto InitialPtr = get(); + // Now update the active member of the union to be the actual pointer-typed + // member so that accessing it indirectly through the returned address is + // valid. + Storage.MinTagPointer = InitialPtr; + // Finally, validate that this was a no-op as expected by reading it back + // out using the same underlying-storage read as above. + assert(InitialPtr == get() && + "Switching to typed storage changed the pointer returned!"); + // Now we can correctly return an address to typed storage. + return &Storage.MinTagPointer; + } + + explicit operator bool() const { + return getOpaqueValue() & HelperT::PointerMask; + } + bool operator==(const PointerSumType &R) const { + return getOpaqueValue() == R.getOpaqueValue(); + } + bool operator!=(const PointerSumType &R) const { + return getOpaqueValue() != R.getOpaqueValue(); + } + bool operator<(const PointerSumType &R) const { + return getOpaqueValue() < R.getOpaqueValue(); + } + bool operator>(const PointerSumType &R) const { + return getOpaqueValue() > R.getOpaqueValue(); + } + bool operator<=(const PointerSumType &R) const { + return getOpaqueValue() <= R.getOpaqueValue(); + } + bool operator>=(const PointerSumType &R) const { + return getOpaqueValue() >= R.getOpaqueValue(); + } + + uintptr_t getOpaqueValue() const { + // Read the underlying storage of the union, regardless of the active + // member. + return bit_cast(Storage); + } protected: - void *getImpl() const { - return reinterpret_cast(Value & HelperT::PointerMask); + void *getVoidPtr() const { + return reinterpret_cast(getOpaqueValue() & HelperT::PointerMask); } }; @@ -151,8 +238,9 @@ struct PointerSumTypeHelper : MemberTs... { enum { NumTagBits = Min::value }; // Also compute the smallest discriminant and various masks for convenience. + constexpr static TagT MinTag = + static_cast(Min::value); enum : uint64_t { - MinTag = Min::value, PointerMask = static_cast(-1) << NumTagBits, TagMask = ~PointerMask }; diff --git a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h index dc8a9b6e78b..d77b12228cb 100644 --- a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h +++ b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h @@ -296,12 +296,15 @@ class ReversePostOrderTraversal { public: using rpo_iterator = typename std::vector::reverse_iterator; + using const_rpo_iterator = typename std::vector::const_reverse_iterator; ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); } // Because we want a reverse post order, use reverse iterators from the vector rpo_iterator begin() { return Blocks.rbegin(); } + const_rpo_iterator begin() const { return Blocks.crbegin(); } rpo_iterator end() { return Blocks.rend(); } + const_rpo_iterator end() const { return Blocks.crend(); } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ADT/STLExtras.h b/contrib/llvm/include/llvm/ADT/STLExtras.h index 94365dd9ced..f66ca7c08a7 100644 --- a/contrib/llvm/include/llvm/ADT/STLExtras.h +++ b/contrib/llvm/include/llvm/ADT/STLExtras.h @@ -21,6 +21,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Config/abi-breaking.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -70,6 +71,16 @@ template struct conjunction : std::conditional, B1>::type {}; +template struct make_const_ptr { + using type = + typename std::add_pointer::type>::type; +}; + +template struct make_const_ref { + using type = typename std::add_lvalue_reference< + typename std::add_const::type>::type; +}; + //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// @@ -194,6 +205,12 @@ void adl_swap(T &&lhs, T &&rhs) noexcept( adl_detail::adl_swap(std::forward(lhs), std::forward(rhs)); } +/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty. +template +constexpr bool empty(const T &RangeOrContainer) { + return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer); +} + // mapped_iterator - This is a simple iterator adapter that causes a function to // be applied whenever operator* is invoked on the iterator. @@ -418,9 +435,94 @@ make_filter_range(RangeT &&Range, PredicateT Pred) { std::end(std::forward(Range)), Pred)); } -// forward declarations required by zip_shortest/zip_first +/// A pseudo-iterator adaptor that is designed to implement "early increment" +/// style loops. +/// +/// This is *not a normal iterator* and should almost never be used directly. It +/// is intended primarily to be used with range based for loops and some range +/// algorithms. +/// +/// The iterator isn't quite an `OutputIterator` or an `InputIterator` but +/// somewhere between them. The constraints of these iterators are: +/// +/// - On construction or after being incremented, it is comparable and +/// dereferencable. It is *not* incrementable. +/// - After being dereferenced, it is neither comparable nor dereferencable, it +/// is only incrementable. +/// +/// This means you can only dereference the iterator once, and you can only +/// increment it once between dereferences. +template +class early_inc_iterator_impl + : public iterator_adaptor_base, + WrappedIteratorT, std::input_iterator_tag> { + using BaseT = + iterator_adaptor_base, + WrappedIteratorT, std::input_iterator_tag>; + + using PointerT = typename std::iterator_traits::pointer; + +protected: +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + bool IsEarlyIncremented = false; +#endif + +public: + early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {} + + using BaseT::operator*; + typename BaseT::reference operator*() { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(!IsEarlyIncremented && "Cannot dereference twice!"); + IsEarlyIncremented = true; +#endif + return *(this->I)++; + } + + using BaseT::operator++; + early_inc_iterator_impl &operator++() { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(IsEarlyIncremented && "Cannot increment before dereferencing!"); + IsEarlyIncremented = false; +#endif + return *this; + } + + using BaseT::operator==; + bool operator==(const early_inc_iterator_impl &RHS) const { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(!IsEarlyIncremented && "Cannot compare after dereferencing!"); +#endif + return BaseT::operator==(RHS); + } +}; + +/// Make a range that does early increment to allow mutation of the underlying +/// range without disrupting iteration. +/// +/// The underlying iterator will be incremented immediately after it is +/// dereferenced, allowing deletion of the current node or insertion of nodes to +/// not disrupt iteration provided they do not invalidate the *next* iterator -- +/// the current iterator can be invalidated. +/// +/// This requires a very exact pattern of use that is only really suitable to +/// range based for loops and other range algorithms that explicitly guarantee +/// to dereference exactly once each element, and to increment exactly once each +/// element. +template +iterator_range>> +make_early_inc_range(RangeT &&Range) { + using EarlyIncIteratorT = + early_inc_iterator_impl>; + return make_range(EarlyIncIteratorT(std::begin(std::forward(Range))), + EarlyIncIteratorT(std::end(std::forward(Range)))); +} + +// forward declarations required by zip_shortest/zip_first/zip_longest template bool all_of(R &&range, UnaryPredicate P); +template +bool any_of(R &&range, UnaryPredicate P); template struct index_sequence; @@ -571,6 +673,132 @@ detail::zippy zip_first(T &&t, U &&u, std::forward(t), std::forward(u), std::forward(args)...); } +namespace detail { +template +static Iter next_or_end(const Iter &I, const Iter &End) { + if (I == End) + return End; + return std::next(I); +} + +template +static auto deref_or_none(const Iter &I, const Iter &End) + -> llvm::Optional::type>::type> { + if (I == End) + return None; + return *I; +} + +template struct ZipLongestItemType { + using type = + llvm::Optional())>::type>::type>; +}; + +template struct ZipLongestTupleType { + using type = std::tuple::type...>; +}; + +template +class zip_longest_iterator + : public iterator_facade_base< + zip_longest_iterator, + typename std::common_type< + std::forward_iterator_tag, + typename std::iterator_traits::iterator_category...>::type, + typename ZipLongestTupleType::type, + typename std::iterator_traits>::type>::difference_type, + typename ZipLongestTupleType::type *, + typename ZipLongestTupleType::type> { +public: + using value_type = typename ZipLongestTupleType::type; + +private: + std::tuple iterators; + std::tuple end_iterators; + + template + bool test(const zip_longest_iterator &other, + index_sequence) const { + return llvm::any_of( + std::initializer_list{std::get(this->iterators) != + std::get(other.iterators)...}, + identity{}); + } + + template value_type deref(index_sequence) const { + return value_type( + deref_or_none(std::get(iterators), std::get(end_iterators))...); + } + + template + decltype(iterators) tup_inc(index_sequence) const { + return std::tuple( + next_or_end(std::get(iterators), std::get(end_iterators))...); + } + +public: + zip_longest_iterator(std::pair... ts) + : iterators(std::forward(ts.first)...), + end_iterators(std::forward(ts.second)...) {} + + value_type operator*() { return deref(index_sequence_for{}); } + + value_type operator*() const { return deref(index_sequence_for{}); } + + zip_longest_iterator &operator++() { + iterators = tup_inc(index_sequence_for{}); + return *this; + } + + bool operator==(const zip_longest_iterator &other) const { + return !test(other, index_sequence_for{}); + } +}; + +template class zip_longest_range { +public: + using iterator = + zip_longest_iterator()))...>; + using iterator_category = typename iterator::iterator_category; + using value_type = typename iterator::value_type; + using difference_type = typename iterator::difference_type; + using pointer = typename iterator::pointer; + using reference = typename iterator::reference; + +private: + std::tuple ts; + + template iterator begin_impl(index_sequence) const { + return iterator(std::make_pair(adl_begin(std::get(ts)), + adl_end(std::get(ts)))...); + } + + template iterator end_impl(index_sequence) const { + return iterator(std::make_pair(adl_end(std::get(ts)), + adl_end(std::get(ts)))...); + } + +public: + zip_longest_range(Args &&... ts_) : ts(std::forward(ts_)...) {} + + iterator begin() const { return begin_impl(index_sequence_for{}); } + iterator end() const { return end_impl(index_sequence_for{}); } +}; +} // namespace detail + +/// Iterate over two or more iterators at the same time. Iteration continues +/// until all iterators reach the end. The llvm::Optional only contains a value +/// if the iterator has not reached the end. +template +detail::zip_longest_range zip_longest(T &&t, U &&u, + Args &&... args) { + return detail::zip_longest_range( + std::forward(t), std::forward(u), std::forward(args)...); +} + /// Iterator wrapper that concatenates sequences together. /// /// This can concatenate different iterators, even with different types, into @@ -593,18 +821,20 @@ class concat_iterator /// Note that something like iterator_range seems nice at first here, but the /// range properties are of little benefit and end up getting in the way /// because we need to do mutation on the current iterators. - std::tuple...> IterPairs; + std::tuple Begins; + std::tuple Ends; /// Attempts to increment a specific iterator. /// /// Returns true if it was able to increment the iterator. Returns false if /// the iterator is already at the end iterator. template bool incrementHelper() { - auto &IterPair = std::get(IterPairs); - if (IterPair.first == IterPair.second) + auto &Begin = std::get(Begins); + auto &End = std::get(Ends); + if (Begin == End) return false; - ++IterPair.first; + ++Begin; return true; } @@ -628,11 +858,12 @@ class concat_iterator /// dereferences the iterator and returns the address of the resulting /// reference. template ValueT *getHelper() const { - auto &IterPair = std::get(IterPairs); - if (IterPair.first == IterPair.second) + auto &Begin = std::get(Begins); + auto &End = std::get(Ends); + if (Begin == End) return nullptr; - return &*IterPair.first; + return &*Begin; } /// Finds the first non-end iterator, dereferences, and returns the resulting @@ -659,7 +890,7 @@ public: /// iterators. template explicit concat_iterator(RangeTs &&... Ranges) - : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {} + : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {} using BaseT::operator++; @@ -671,7 +902,7 @@ public: ValueT &operator*() const { return get(index_sequence_for()); } bool operator==(const concat_iterator &RHS) const { - return IterPairs == RHS.IterPairs; + return Begins == RHS.Begins && Ends == RHS.Ends; } }; @@ -740,6 +971,19 @@ struct less_second { } }; +/// \brief Function object to apply a binary function to the first component of +/// a std::pair. +template +struct on_first { + FuncTy func; + + template + auto operator()(const T &lhs, const T &rhs) const + -> decltype(func(lhs.first, rhs.first)) { + return func(lhs.first, rhs.first); + } +}; + // A subset of N3658. More stuff can be added as-needed. /// Represents a compile-time sequence of integers. @@ -877,6 +1121,10 @@ inline void sort(IteratorTy Start, IteratorTy End) { std::sort(Start, End); } +template inline void sort(Container &&C) { + llvm::sort(adl_begin(C), adl_end(C)); +} + template inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { #ifdef EXPENSIVE_CHECKS @@ -886,6 +1134,11 @@ inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { std::sort(Start, End, Comp); } +template +inline void sort(Container &&C, Compare Comp) { + llvm::sort(adl_begin(C), adl_end(C), Comp); +} + //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// @@ -908,6 +1161,18 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +/// Get the size of a range. This is a wrapper function around std::distance +/// which is only enabled when the operation is O(1). +template +auto size(R &&Range, typename std::enable_if< + std::is_same::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) + -> decltype(std::distance(Range.begin(), Range.end())) { + return std::distance(Range.begin(), Range.end()); +} + /// Provide wrappers to std::for_each which take ranges instead of having to /// pass begin/end explicitly. template @@ -1018,6 +1283,33 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { return std::lower_bound(adl_begin(Range), adl_end(Range), I); } +template +auto lower_bound(R &&Range, ForwardIt I, Compare C) + -> decltype(adl_begin(Range)) { + return std::lower_bound(adl_begin(Range), adl_end(Range), I, C); +} + +/// Provide wrappers to std::upper_bound which take ranges instead of having to +/// pass begin/end explicitly. +template +auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { + return std::upper_bound(adl_begin(Range), adl_end(Range), I); +} + +template +auto upper_bound(R &&Range, ForwardIt I, Compare C) + -> decltype(adl_begin(Range)) { + return std::upper_bound(adl_begin(Range), adl_end(Range), I, C); +} +/// Wrapper function around std::equal to detect if all elements +/// in a container are same. +template +bool is_splat(R &&Range) { + size_t range_size = size(Range); + return range_size != 0 && (range_size == 1 || + std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); +} + /// Given a range of type R, iterate the entire range and return a /// SmallVector with elements of the vector. This is useful, for example, /// when you want to iterate a range and then sort the results. @@ -1039,18 +1331,6 @@ void erase_if(Container &C, UnaryPredicate P) { C.erase(remove_if(C, P), C.end()); } -/// Get the size of a range. This is a wrapper function around std::distance -/// which is only enabled when the operation is O(1). -template -auto size(R &&Range, typename std::enable_if< - std::is_same::iterator_category, - std::random_access_iterator_tag>::value, - void>::type * = nullptr) - -> decltype(std::distance(Range.begin(), Range.end())) { - return std::distance(Range.begin(), Range.end()); -} - //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// @@ -1263,6 +1543,40 @@ auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( Indices{}); } +/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N) +/// time. Not meant for use with random-access iterators. +template +bool hasNItems( + IterTy &&Begin, IterTy &&End, unsigned N, + typename std::enable_if< + !std::is_same< + typename std::iterator_traits::type>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) { + for (; N; --N, ++Begin) + if (Begin == End) + return false; // Too few. + return Begin == End; +} + +/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N) +/// time. Not meant for use with random-access iterators. +template +bool hasNItemsOrMore( + IterTy &&Begin, IterTy &&End, unsigned N, + typename std::enable_if< + !std::is_same< + typename std::iterator_traits::type>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) { + for (; N; --N, ++Begin) + if (Begin == End) + return false; // Too few. + return true; +} + } // end namespace llvm #endif // LLVM_ADT_STLEXTRAS_H diff --git a/contrib/llvm/include/llvm/ADT/SmallBitVector.h b/contrib/llvm/include/llvm/ADT/SmallBitVector.h index b6391746639..0a73dbd6067 100644 --- a/contrib/llvm/include/llvm/ADT/SmallBitVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallBitVector.h @@ -92,10 +92,6 @@ public: }; private: - bool isSmall() const { - return X & uintptr_t(1); - } - BitVector *getPointer() const { assert(!isSmall()); return reinterpret_cast(X); @@ -186,6 +182,8 @@ public: return make_range(set_bits_begin(), set_bits_end()); } + bool isSmall() const { return X & uintptr_t(1); } + /// Tests whether there are no bits in this bitvector. bool empty() const { return isSmall() ? getSmallSize() == 0 : getPointer()->empty(); @@ -242,7 +240,7 @@ public: uintptr_t Bits = getSmallBits(); if (Bits == 0) return -1; - return NumBaseBits - countLeadingZeros(Bits); + return NumBaseBits - countLeadingZeros(Bits) - 1; } return getPointer()->find_last(); } @@ -265,7 +263,9 @@ public: return -1; uintptr_t Bits = getSmallBits(); - return NumBaseBits - countLeadingOnes(Bits); + // Set unused bits. + Bits |= ~uintptr_t(0) << getSmallSize(); + return NumBaseBits - countLeadingOnes(Bits) - 1; } return getPointer()->find_last_unset(); } @@ -465,6 +465,11 @@ public: return (*this)[Idx]; } + // Push single bit to end of vector. + void push_back(bool Val) { + resize(size() + 1, Val); + } + /// Test if any common bits are set. bool anyCommon(const SmallBitVector &RHS) const { if (isSmall() && RHS.isSmall()) @@ -482,10 +487,17 @@ public: bool operator==(const SmallBitVector &RHS) const { if (size() != RHS.size()) return false; - if (isSmall()) + if (isSmall() && RHS.isSmall()) return getSmallBits() == RHS.getSmallBits(); - else + else if (!isSmall() && !RHS.isSmall()) return *getPointer() == *RHS.getPointer(); + else { + for (size_t i = 0, e = size(); i != e; ++i) { + if ((*this)[i] != RHS[i]) + return false; + } + return true; + } } bool operator!=(const SmallBitVector &RHS) const { @@ -493,16 +505,19 @@ public: } // Intersection, union, disjoint union. + // FIXME BitVector::operator&= does not resize the LHS but this does SmallBitVector &operator&=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); - if (isSmall()) + if (isSmall() && RHS.isSmall()) setSmallBits(getSmallBits() & RHS.getSmallBits()); - else if (!RHS.isSmall()) + else if (!isSmall() && !RHS.isSmall()) getPointer()->operator&=(*RHS.getPointer()); else { - SmallBitVector Copy = RHS; - Copy.resize(size()); - getPointer()->operator&=(*Copy.getPointer()); + size_t i, e; + for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + (*this)[i] = test(i) && RHS.test(i); + for (e = size(); i != e; ++i) + reset(i); } return *this; } @@ -542,28 +557,26 @@ public: SmallBitVector &operator|=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); - if (isSmall()) + if (isSmall() && RHS.isSmall()) setSmallBits(getSmallBits() | RHS.getSmallBits()); - else if (!RHS.isSmall()) + else if (!isSmall() && !RHS.isSmall()) getPointer()->operator|=(*RHS.getPointer()); else { - SmallBitVector Copy = RHS; - Copy.resize(size()); - getPointer()->operator|=(*Copy.getPointer()); + for (size_t i = 0, e = RHS.size(); i != e; ++i) + (*this)[i] = test(i) || RHS.test(i); } return *this; } SmallBitVector &operator^=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); - if (isSmall()) + if (isSmall() && RHS.isSmall()) setSmallBits(getSmallBits() ^ RHS.getSmallBits()); - else if (!RHS.isSmall()) + else if (!isSmall() && !RHS.isSmall()) getPointer()->operator^=(*RHS.getPointer()); else { - SmallBitVector Copy = RHS; - Copy.resize(size()); - getPointer()->operator^=(*Copy.getPointer()); + for (size_t i = 0, e = RHS.size(); i != e; ++i) + (*this)[i] = test(i) != RHS.test(i); } return *this; } diff --git a/contrib/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm/include/llvm/ADT/SmallVector.h index acb4426b4f4..0636abbb1fb 100644 --- a/contrib/llvm/include/llvm/ADT/SmallVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallVector.h @@ -182,7 +182,7 @@ public: /// SmallVectorTemplateBase - This is where we put method /// implementations that are designed to work with non-POD-like T's. -template +template ::value> class SmallVectorTemplateBase : public SmallVectorTemplateCommon { protected: SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} @@ -299,7 +299,7 @@ protected: // use memcpy here. Note that I and E are iterators and thus might be // invalid for memcpy if they are equal. if (I != E) - memcpy(Dest, I, (E - I) * sizeof(T)); + memcpy(reinterpret_cast(Dest), I, (E - I) * sizeof(T)); } /// Double the size of the allocated memory, guaranteeing space for at @@ -310,7 +310,7 @@ public: void push_back(const T &Elt) { if (LLVM_UNLIKELY(this->size() >= this->capacity())) this->grow(); - memcpy(this->end(), &Elt, sizeof(T)); + memcpy(reinterpret_cast(this->end()), &Elt, sizeof(T)); this->set_size(this->size() + 1); } @@ -320,8 +320,8 @@ public: /// This class consists of common code factored out of the SmallVector class to /// reduce code duplication based on the SmallVector 'N' template parameter. template -class SmallVectorImpl : public SmallVectorTemplateBase::value> { - using SuperClass = SmallVectorTemplateBase::value>; +class SmallVectorImpl : public SmallVectorTemplateBase { + using SuperClass = SmallVectorTemplateBase; public: using iterator = typename SuperClass::iterator; diff --git a/contrib/llvm/include/llvm/ADT/SparseBitVector.h b/contrib/llvm/include/llvm/ADT/SparseBitVector.h index 4cbf40c7680..84e73bcbace 100644 --- a/contrib/llvm/include/llvm/ADT/SparseBitVector.h +++ b/contrib/llvm/include/llvm/ADT/SparseBitVector.h @@ -261,21 +261,33 @@ class SparseBitVector { BITWORD_SIZE = SparseBitVectorElement::BITWORD_SIZE }; - // Pointer to our current Element. - ElementListIter CurrElementIter; ElementList Elements; + // Pointer to our current Element. This has no visible effect on the external + // state of a SparseBitVector, it's just used to improve performance in the + // common case of testing/modifying bits with similar indices. + mutable ElementListIter CurrElementIter; // This is like std::lower_bound, except we do linear searching from the // current position. - ElementListIter FindLowerBound(unsigned ElementIndex) { + ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const { + + // We cache a non-const iterator so we're forced to resort to const_cast to + // get the begin/end in the case where 'this' is const. To avoid duplication + // of code with the only difference being whether the const cast is present + // 'this' is always const in this particular function and we sort out the + // difference in FindLowerBound and FindLowerBoundConst. + ElementListIter Begin = + const_cast *>(this)->Elements.begin(); + ElementListIter End = + const_cast *>(this)->Elements.end(); if (Elements.empty()) { - CurrElementIter = Elements.begin(); - return Elements.begin(); + CurrElementIter = Begin; + return CurrElementIter; } // Make sure our current iterator is valid. - if (CurrElementIter == Elements.end()) + if (CurrElementIter == End) --CurrElementIter; // Search from our current iterator, either backwards or forwards, @@ -284,17 +296,23 @@ class SparseBitVector { if (CurrElementIter->index() == ElementIndex) { return ElementIter; } else if (CurrElementIter->index() > ElementIndex) { - while (ElementIter != Elements.begin() + while (ElementIter != Begin && ElementIter->index() > ElementIndex) --ElementIter; } else { - while (ElementIter != Elements.end() && + while (ElementIter != End && ElementIter->index() < ElementIndex) ++ElementIter; } CurrElementIter = ElementIter; return ElementIter; } + ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const { + return FindLowerBoundImpl(ElementIndex); + } + ElementListIter FindLowerBound(unsigned ElementIndex) { + return FindLowerBoundImpl(ElementIndex); + } // Iterator to walk set bits in the bitmap. This iterator is a lot uglier // than it would be, in order to be efficient. @@ -423,22 +441,12 @@ class SparseBitVector { public: using iterator = SparseBitVectorIterator; - SparseBitVector() { - CurrElementIter = Elements.begin(); - } + SparseBitVector() : Elements(), CurrElementIter(Elements.begin()) {} - // SparseBitVector copy ctor. - SparseBitVector(const SparseBitVector &RHS) { - ElementListConstIter ElementIter = RHS.Elements.begin(); - while (ElementIter != RHS.Elements.end()) { - Elements.push_back(SparseBitVectorElement(*ElementIter)); - ++ElementIter; - } - - CurrElementIter = Elements.begin (); - } - - ~SparseBitVector() = default; + SparseBitVector(const SparseBitVector &RHS) + : Elements(RHS.Elements), CurrElementIter(Elements.begin()) {} + SparseBitVector(SparseBitVector &&RHS) + : Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {} // Clear. void clear() { @@ -450,26 +458,23 @@ public: if (this == &RHS) return *this; - Elements.clear(); - - ElementListConstIter ElementIter = RHS.Elements.begin(); - while (ElementIter != RHS.Elements.end()) { - Elements.push_back(SparseBitVectorElement(*ElementIter)); - ++ElementIter; - } - - CurrElementIter = Elements.begin (); - + Elements = RHS.Elements; + CurrElementIter = Elements.begin(); + return *this; + } + SparseBitVector &operator=(SparseBitVector &&RHS) { + Elements = std::move(RHS.Elements); + CurrElementIter = Elements.begin(); return *this; } // Test, Reset, and Set a bit in the bitmap. - bool test(unsigned Idx) { + bool test(unsigned Idx) const { if (Elements.empty()) return false; unsigned ElementIndex = Idx / ElementSize; - ElementListIter ElementIter = FindLowerBound(ElementIndex); + ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex); // If we can't find an element that is supposed to contain this bit, there // is nothing more to do. diff --git a/contrib/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm/include/llvm/ADT/StringExtras.h index 71b0e7527cb..60a03633a8a 100644 --- a/contrib/llvm/include/llvm/ADT/StringExtras.h +++ b/contrib/llvm/include/llvm/ADT/StringExtras.h @@ -139,22 +139,23 @@ inline std::string utohexstr(uint64_t X, bool LowerCase = false) { /// Convert buffer \p Input to its hexadecimal representation. /// The returned string is double the size of \p Input. -inline std::string toHex(StringRef Input) { +inline std::string toHex(StringRef Input, bool LowerCase = false) { static const char *const LUT = "0123456789ABCDEF"; + const uint8_t Offset = LowerCase ? 32 : 0; size_t Length = Input.size(); std::string Output; Output.reserve(2 * Length); for (size_t i = 0; i < Length; ++i) { const unsigned char c = Input[i]; - Output.push_back(LUT[c >> 4]); - Output.push_back(LUT[c & 15]); + Output.push_back(LUT[c >> 4] | Offset); + Output.push_back(LUT[c & 15] | Offset); } return Output; } -inline std::string toHex(ArrayRef Input) { - return toHex(toStringRef(Input)); +inline std::string toHex(ArrayRef Input, bool LowerCase = false) { + return toHex(toStringRef(Input), LowerCase); } inline uint8_t hexFromNibbles(char MSB, char LSB) { diff --git a/contrib/llvm/include/llvm/ADT/Triple.h b/contrib/llvm/include/llvm/ADT/Triple.h index c95b16dd4e8..e06a68e2731 100644 --- a/contrib/llvm/include/llvm/ADT/Triple.h +++ b/contrib/llvm/include/llvm/ADT/Triple.h @@ -55,12 +55,11 @@ public: bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) hexagon, // Hexagon: hexagon - mips, // MIPS: mips, mipsallegrex - mipsel, // MIPSEL: mipsel, mipsallegrexel - mips64, // MIPS64: mips64 - mips64el, // MIPS64EL: mips64el + mips, // MIPS: mips, mipsallegrex, mipsr6 + mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el + mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 + mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el msp430, // MSP430: msp430 - nios2, // NIOSII: nios2 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le @@ -101,6 +100,7 @@ public: enum SubArchType { NoSubArch, + ARMSubArch_v8_5a, ARMSubArch_v8_4a, ARMSubArch_v8_3a, ARMSubArch_v8_2a, @@ -125,7 +125,9 @@ public: KalimbaSubArch_v3, KalimbaSubArch_v4, - KalimbaSubArch_v5 + KalimbaSubArch_v5, + + MipsSubArch_r6 }; enum VendorType { UnknownVendor, @@ -182,7 +184,10 @@ public: Mesa3D, Contiki, AMDPAL, // AMD PAL Runtime - LastOSType = AMDPAL + HermitCore, // HermitCore Unikernel/Multikernel + Hurd, // GNU/Hurd + WASI, // Experimental WebAssembly OS + LastOSType = WASI }; enum EnvironmentType { UnknownEnvironment, @@ -578,9 +583,20 @@ public: return getOS() == Triple::KFreeBSD; } + /// Tests whether the OS is Hurd. + bool isOSHurd() const { + return getOS() == Triple::Hurd; + } + + /// Tests whether the OS is WASI. + bool isOSWASI() const { + return getOS() == Triple::WASI; + } + /// Tests whether the OS uses glibc. bool isOSGlibc() const { - return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD) && + return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD || + getOS() == Triple::Hurd) && !isAndroid(); } diff --git a/contrib/llvm/include/llvm/ADT/bit.h b/contrib/llvm/include/llvm/ADT/bit.h new file mode 100644 index 00000000000..a4aba7b6a9e --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/bit.h @@ -0,0 +1,59 @@ +//===-- llvm/ADT/bit.h - C++20 ----------------------------*- 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 C++20 header. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BIT_H +#define LLVM_ADT_BIT_H + +#include "llvm/Support/Compiler.h" +#include +#include + +namespace llvm { + +// This implementation of bit_cast is different from the C++17 one in two ways: +// - It isn't constexpr because that requires compiler support. +// - It requires trivially-constructible To, to avoid UB in the implementation. +template ::type +#if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) + , typename = typename std::is_trivially_constructible::type +#elif __has_feature(is_trivially_constructible) + , typename = typename std::enable_if<__is_trivially_constructible(To)>::type +#else + // See comment below. +#endif +#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) + , typename = typename std::enable_if::value>::type + , typename = typename std::enable_if::value>::type +#elif __has_feature(is_trivially_copyable) + , typename = typename std::enable_if<__is_trivially_copyable(To)>::type + , typename = typename std::enable_if<__is_trivially_copyable(From)>::type +#else + // This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike + // llvm/Support/type_traits.h's isPodLike we don't want to provide a + // good-enough answer here: developers in that configuration will hit + // compilation failures on the bots instead of locally. That's acceptable + // because it's very few developers, and only until we move past C++11. +#endif +> +inline To bit_cast(const From &from) noexcept { + To to; + std::memcpy(&to, &from, sizeof(To)); + return to; +} + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/ADT/iterator.h b/contrib/llvm/include/llvm/ADT/iterator.h index 549c5221173..40e490cf786 100644 --- a/contrib/llvm/include/llvm/ADT/iterator.h +++ b/contrib/llvm/include/llvm/ADT/iterator.h @@ -202,9 +202,7 @@ template < typename ReferenceT = typename std::conditional< std::is_same::value_type>::value, - typename std::iterator_traits::reference, T &>::type, - // Don't provide these, they are mostly to act as aliases below. - typename WrappedTraitsT = std::iterator_traits> + typename std::iterator_traits::reference, T &>::type> class iterator_adaptor_base : public iterator_facade_base { @@ -311,8 +309,10 @@ make_pointee_range(RangeT &&Range) { template ())> class pointer_iterator - : public iterator_adaptor_base, - WrappedIteratorT, T> { + : public iterator_adaptor_base< + pointer_iterator, WrappedIteratorT, + typename std::iterator_traits::iterator_category, + T> { mutable T Ptr; public: @@ -334,6 +334,34 @@ make_pointer_range(RangeT &&Range) { PointerIteratorT(std::end(std::forward(Range)))); } +// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType, +// to create NodeRef = std::pair. +template +class WrappedPairNodeDataIterator + : public iterator_adaptor_base< + WrappedPairNodeDataIterator, ItType, + typename std::iterator_traits::iterator_category, NodeRef, + std::ptrdiff_t, NodeRef *, NodeRef &> { + using BaseT = iterator_adaptor_base< + WrappedPairNodeDataIterator, ItType, + typename std::iterator_traits::iterator_category, NodeRef, + std::ptrdiff_t, NodeRef *, NodeRef &>; + + const DataRef DR; + mutable NodeRef NR; + +public: + WrappedPairNodeDataIterator(ItType Begin, const DataRef DR) + : BaseT(Begin), DR(DR) { + NR.first = DR; + } + + NodeRef &operator*() const { + NR.second = *this->I; + return NR; + } +}; + } // end namespace llvm #endif // LLVM_ADT_ITERATOR_H diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h index be3496bbd95..e2a2ac0622e 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -43,7 +43,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -335,8 +334,7 @@ public: /// A convenience wrapper around the primary \c alias interface. AliasResult alias(const Value *V1, const Value *V2) { - return alias(V1, MemoryLocation::UnknownSize, V2, - MemoryLocation::UnknownSize); + return alias(V1, LocationSize::unknown(), V2, LocationSize::unknown()); } /// A trivial helper function to check to see if the specified pointers are @@ -364,7 +362,8 @@ public: /// A convenience wrapper around the \c isMustAlias helper interface. bool isMustAlias(const Value *V1, const Value *V2) { - return alias(V1, 1, V2, 1) == MustAlias; + return alias(V1, LocationSize::precise(1), V2, LocationSize::precise(1)) == + MustAlias; } /// Checks whether the given location points to constant memory, or if @@ -382,15 +381,15 @@ public: /// \name Simple mod/ref information /// @{ - /// Get the ModRef info associated with a pointer argument of a callsite. The + /// Get the ModRef info associated with a pointer argument of a call. The /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note /// that these bits do not necessarily account for the overall behavior of /// the function, but rather only provide additional per-argument /// information. This never sets ModRefInfo::Must. - ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx); + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); /// Return the behavior of the given call site. - FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS); + FunctionModRefBehavior getModRefBehavior(const CallBase *Call); /// Return the behavior when calling the given function. FunctionModRefBehavior getModRefBehavior(const Function *F); @@ -406,8 +405,8 @@ public: /// property (e.g. calls to 'sin' and 'cos'). /// /// This property corresponds to the GCC 'const' attribute. - bool doesNotAccessMemory(ImmutableCallSite CS) { - return getModRefBehavior(CS) == FMRB_DoesNotAccessMemory; + bool doesNotAccessMemory(const CallBase *Call) { + return getModRefBehavior(Call) == FMRB_DoesNotAccessMemory; } /// Checks if the specified function is known to never read or write memory. @@ -434,8 +433,8 @@ public: /// absence of interfering store instructions, such as CSE of strlen calls. /// /// This property corresponds to the GCC 'pure' attribute. - bool onlyReadsMemory(ImmutableCallSite CS) { - return onlyReadsMemory(getModRefBehavior(CS)); + bool onlyReadsMemory(const CallBase *Call) { + return onlyReadsMemory(getModRefBehavior(Call)); } /// Checks if the specified function is known to only read from non-volatile @@ -500,36 +499,12 @@ public: /// getModRefInfo (for call sites) - Return information about whether /// a particular call site modifies or reads the specified memory location. - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); /// getModRefInfo (for call sites) - A convenience wrapper. - ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P, + ModRefInfo getModRefInfo(const CallBase *Call, const Value *P, LocationSize Size) { - return getModRefInfo(CS, MemoryLocation(P, Size)); - } - - /// getModRefInfo (for calls) - Return information about whether - /// a particular call modifies or reads the specified memory location. - ModRefInfo getModRefInfo(const CallInst *C, const MemoryLocation &Loc) { - return getModRefInfo(ImmutableCallSite(C), Loc); - } - - /// getModRefInfo (for calls) - A convenience wrapper. - ModRefInfo getModRefInfo(const CallInst *C, const Value *P, - LocationSize Size) { - return getModRefInfo(C, MemoryLocation(P, Size)); - } - - /// getModRefInfo (for invokes) - Return information about whether - /// a particular invoke modifies or reads the specified memory location. - ModRefInfo getModRefInfo(const InvokeInst *I, const MemoryLocation &Loc) { - return getModRefInfo(ImmutableCallSite(I), Loc); - } - - /// getModRefInfo (for invokes) - A convenience wrapper. - ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P, - LocationSize Size) { - return getModRefInfo(I, MemoryLocation(P, Size)); + return getModRefInfo(Call, MemoryLocation(P, Size)); } /// getModRefInfo (for loads) - Return information about whether @@ -569,7 +544,7 @@ public: /// getModRefInfo (for cmpxchges) - A convenience wrapper. ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, const Value *P, - unsigned Size) { + LocationSize Size) { return getModRefInfo(CX, MemoryLocation(P, Size)); } @@ -579,7 +554,7 @@ public: /// getModRefInfo (for atomicrmws) - A convenience wrapper. ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const Value *P, - unsigned Size) { + LocationSize Size) { return getModRefInfo(RMW, MemoryLocation(P, Size)); } @@ -626,8 +601,8 @@ public: ModRefInfo getModRefInfo(const Instruction *I, const Optional &OptLoc) { if (OptLoc == None) { - if (auto CS = ImmutableCallSite(I)) { - return createModRefInfo(getModRefBehavior(CS)); + if (const auto *Call = dyn_cast(I)) { + return createModRefInfo(getModRefBehavior(Call)); } } @@ -661,12 +636,12 @@ public: /// Return information about whether a call and an instruction may refer to /// the same memory locations. - ModRefInfo getModRefInfo(Instruction *I, ImmutableCallSite Call); + ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call); /// Return information about whether two call sites may refer to the same set /// of memory locations. See the AA documentation for details: /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo - ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); /// Return information about whether a particular call site modifies /// or reads the specified memory location \p MemLoc before instruction \p I @@ -777,25 +752,25 @@ public: /// that these bits do not necessarily account for the overall behavior of /// the function, but rather only provide additional per-argument /// information. - virtual ModRefInfo getArgModRefInfo(ImmutableCallSite CS, + virtual ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) = 0; /// Return the behavior of the given call site. - virtual FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) = 0; + virtual FunctionModRefBehavior getModRefBehavior(const CallBase *Call) = 0; /// Return the behavior when calling the given function. virtual FunctionModRefBehavior getModRefBehavior(const Function *F) = 0; /// getModRefInfo (for call sites) - Return information about whether /// a particular call site modifies or reads the specified memory location. - virtual ModRefInfo getModRefInfo(ImmutableCallSite CS, + virtual ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) = 0; /// Return information about whether two call sites may refer to the same set /// of memory locations. See the AA documentation for details: /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo - virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1, - ImmutableCallSite CS2) = 0; + virtual ModRefInfo getModRefInfo(const CallBase *Call1, + const CallBase *Call2) = 0; /// @} }; @@ -827,26 +802,26 @@ public: return Result.pointsToConstantMemory(Loc, OrLocal); } - ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) override { - return Result.getArgModRefInfo(CS, ArgIdx); + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) override { + return Result.getArgModRefInfo(Call, ArgIdx); } - FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override { - return Result.getModRefBehavior(CS); + FunctionModRefBehavior getModRefBehavior(const CallBase *Call) override { + return Result.getModRefBehavior(Call); } FunctionModRefBehavior getModRefBehavior(const Function *F) override { return Result.getModRefBehavior(F); } - ModRefInfo getModRefInfo(ImmutableCallSite CS, + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) override { - return Result.getModRefInfo(CS, Loc); + return Result.getModRefInfo(Call, Loc); } - ModRefInfo getModRefInfo(ImmutableCallSite CS1, - ImmutableCallSite CS2) override { - return Result.getModRefInfo(CS1, CS2); + ModRefInfo getModRefInfo(const CallBase *Call1, + const CallBase *Call2) override { + return Result.getModRefInfo(Call1, Call2); } }; @@ -901,25 +876,28 @@ protected: : CurrentResult.pointsToConstantMemory(Loc, OrLocal); } - ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) { - return AAR ? AAR->getArgModRefInfo(CS, ArgIdx) : CurrentResult.getArgModRefInfo(CS, ArgIdx); + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { + return AAR ? AAR->getArgModRefInfo(Call, ArgIdx) + : CurrentResult.getArgModRefInfo(Call, ArgIdx); } - FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) { - return AAR ? AAR->getModRefBehavior(CS) : CurrentResult.getModRefBehavior(CS); + FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { + return AAR ? AAR->getModRefBehavior(Call) + : CurrentResult.getModRefBehavior(Call); } FunctionModRefBehavior getModRefBehavior(const Function *F) { return AAR ? AAR->getModRefBehavior(F) : CurrentResult.getModRefBehavior(F); } - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) { - return AAR ? AAR->getModRefInfo(CS, Loc) - : CurrentResult.getModRefInfo(CS, Loc); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { + return AAR ? AAR->getModRefInfo(Call, Loc) + : CurrentResult.getModRefInfo(Call, Loc); } - ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { - return AAR ? AAR->getModRefInfo(CS1, CS2) : CurrentResult.getModRefInfo(CS1, CS2); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) { + return AAR ? AAR->getModRefInfo(Call1, Call2) + : CurrentResult.getModRefInfo(Call1, Call2); } }; @@ -951,11 +929,11 @@ public: return false; } - ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) { + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { return ModRefInfo::ModRef; } - FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) { + FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { return FMRB_UnknownModRefBehavior; } @@ -963,11 +941,11 @@ public: return FMRB_UnknownModRefBehavior; } - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) { + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { return ModRefInfo::ModRef; } - ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) { return ModRefInfo::ModRef; } }; @@ -1075,6 +1053,29 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override; }; +/// A wrapper pass for external alias analyses. This just squirrels away the +/// callback used to run any analyses and register their results. +struct ExternalAAWrapperPass : ImmutablePass { + using CallbackT = std::function; + + CallbackT CB; + + static char ID; + + ExternalAAWrapperPass() : ImmutablePass(ID) { + initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + explicit ExternalAAWrapperPass(CallbackT CB) + : ImmutablePass(ID), CB(std::move(CB)) { + initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; + FunctionPass *createAAResultsWrapperPass(); /// A wrapper pass around a callback which can be used to populate the diff --git a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h index c9680ff40d1..7ed5cd5c473 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h +++ b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h @@ -52,9 +52,13 @@ class AliasSet : public ilist_node { PointerRec **PrevInList = nullptr; PointerRec *NextInList = nullptr; AliasSet *AS = nullptr; - LocationSize Size = 0; + LocationSize Size = LocationSize::mapEmpty(); AAMDNodes AAInfo; + // Whether the size for this record has been set at all. This makes no + // guarantees about the size being known. + bool isSizeSet() const { return Size != LocationSize::mapEmpty(); } + public: PointerRec(Value *V) : Val(V), AAInfo(DenseMapInfo::getEmptyKey()) {} @@ -71,9 +75,10 @@ class AliasSet : public ilist_node { bool updateSizeAndAAInfo(LocationSize NewSize, const AAMDNodes &NewAAInfo) { bool SizeChanged = false; - if (NewSize > Size) { - Size = NewSize; - SizeChanged = true; + if (NewSize != Size) { + LocationSize OldSize = Size; + Size = isSizeSet() ? Size.unionWith(NewSize) : NewSize; + SizeChanged = OldSize != Size; } if (AAInfo == DenseMapInfo::getEmptyKey()) @@ -91,7 +96,10 @@ class AliasSet : public ilist_node { return SizeChanged; } - LocationSize getSize() const { return Size; } + LocationSize getSize() const { + assert(isSizeSet() && "Getting an unset size!"); + return Size; + } /// Return the AAInfo, or null if there is no information or conflicting /// information. @@ -175,9 +183,6 @@ class AliasSet : public ilist_node { }; unsigned Alias : 1; - /// True if this alias set contains volatile loads or stores. - unsigned Volatile : 1; - unsigned SetSize = 0; void addRef() { ++RefCount; } @@ -203,9 +208,6 @@ public: bool isMustAlias() const { return Alias == SetMustAlias; } bool isMayAlias() const { return Alias == SetMayAlias; } - /// Return true if this alias set contains volatile loads or stores. - bool isVolatile() const { return Volatile; } - /// Return true if this alias set should be ignored as part of the /// AliasSetTracker object. bool isForwardingAliasSet() const { return Forward; } @@ -224,6 +226,10 @@ public: // track of the list's exact size. unsigned size() { return SetSize; } + /// If this alias set is known to contain a single instruction and *only* a + /// single unique instruction, return it. Otherwise, return nullptr. + Instruction* getUniqueInstruction(); + void print(raw_ostream &OS) const; void dump() const; @@ -264,7 +270,7 @@ private: // Can only be created by AliasSetTracker. AliasSet() : PtrListEnd(&PtrList), RefCount(0), AliasAny(false), Access(NoAccess), - Alias(SetMustAlias), Volatile(false) {} + Alias(SetMustAlias) {} PointerRec *getSomePointer() const { return PtrList; @@ -303,8 +309,6 @@ private: dropRef(AST); } - void setVolatile() { Volatile = true; } - public: /// Return true if the specified pointer "may" (or must) alias one of the /// members in the set. @@ -379,23 +383,11 @@ public: /// Return the alias sets that are active. const ilist &getAliasSets() const { return AliasSets; } - /// Return the alias set that the specified pointer lives in. If the New - /// argument is non-null, this method sets the value to true if a new alias - /// set is created to contain the pointer (because the pointer didn't alias - /// anything). - AliasSet &getAliasSetForPointer(Value *P, LocationSize Size, - const AAMDNodes &AAInfo); - - /// Return the alias set containing the location specified if one exists, - /// otherwise return null. - AliasSet *getAliasSetForPointerIfExists(const Value *P, LocationSize Size, - const AAMDNodes &AAInfo) { - return mergeAliasSetsForPointer(P, Size, AAInfo); - } - - /// Return true if the specified instruction "may" (or must) alias one of the - /// members in any of the sets. - bool containsUnknown(const Instruction *I) const; + /// Return the alias set which contains the specified memory location. If + /// the memory location aliases two or more existing alias sets, will have + /// the effect of merging those alias sets before the single resulting alias + /// set is returned. + AliasSet &getAliasSetFor(const MemoryLocation &MemLoc); /// Return the underlying alias analysis object used by this tracker. AliasAnalysis &getAliasAnalysis() const { return AA; } @@ -445,8 +437,7 @@ private: return *Entry; } - AliasSet &addPointer(Value *P, LocationSize Size, const AAMDNodes &AAInfo, - AliasSet::AccessLattice E); + AliasSet &addPointer(MemoryLocation Loc, AliasSet::AccessLattice E); AliasSet *mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo); diff --git a/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h index 6344e84b58e..820d7ac0935 100644 --- a/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h @@ -21,7 +21,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/MemoryLocation.h" -#include "llvm/IR/CallSite.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include @@ -84,18 +84,18 @@ public: AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); - ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); /// Chases pointers until we find a (constant global) or not. bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal); /// Get the location associated with a pointer argument of a callsite. - ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx); + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); /// Returns the behavior when calling the given call site. - FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS); + FunctionModRefBehavior getModRefBehavior(const CallBase *Call); /// Returns the behavior when calling the given function. For use when the /// call site is not known. @@ -115,7 +115,7 @@ private: unsigned ZExtBits; unsigned SExtBits; - int64_t Scale; + APInt Scale; bool operator==(const VariableGEPIndex &Other) const { return V == Other.V && ZExtBits == Other.ZExtBits && @@ -133,10 +133,10 @@ private: // Base pointer of the GEP const Value *Base; // Total constant offset w.r.t the base from indexing into structs - int64_t StructOffset; + APInt StructOffset; // Total constant offset w.r.t the base from indexing through // pointers/arrays/vectors - int64_t OtherOffset; + APInt OtherOffset; // Scaled variable (non-constant) indices. SmallVector VarIndices; }; @@ -189,7 +189,7 @@ private: bool constantOffsetHeuristic(const SmallVectorImpl &VarIndices, LocationSize V1Size, LocationSize V2Size, - int64_t BaseOffset, AssumptionCache *AC, + APInt BaseOffset, AssumptionCache *AC, DominatorTree *DT); bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2); diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h index ca12db6208b..0b261873569 100644 --- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h @@ -56,7 +56,7 @@ public: const Function *getFunction() const; const BranchProbabilityInfo *getBPI() const; - void view() const; + void view(StringRef = "BlockFrequencyDAGs") const; /// getblockFreq - Return block frequency. Return 0 if we don't have the /// information. Please note that initial frequency is equal to ENTRY_FREQ. It diff --git a/contrib/llvm/include/llvm/Analysis/CFG.h b/contrib/llvm/include/llvm/Analysis/CFG.h index cccdd163741..caae0b6e2a8 100644 --- a/contrib/llvm/include/llvm/Analysis/CFG.h +++ b/contrib/llvm/include/llvm/Analysis/CFG.h @@ -25,7 +25,6 @@ class DominatorTree; class Function; class Instruction; class LoopInfo; -class TerminatorInst; /// Analyze the specified function to find all of the loop backedges in the /// function and return them. This is a relatively cheap (compared to @@ -46,7 +45,7 @@ unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ); /// edges from a block with multiple successors to a block with multiple /// predecessors. /// -bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, +bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges = false); /// Determine whether instruction 'To' is reachable from 'From', diff --git a/contrib/llvm/include/llvm/Analysis/CFGPrinter.h b/contrib/llvm/include/llvm/Analysis/CFGPrinter.h index 5786769cc50..5996dd90bcf 100644 --- a/contrib/llvm/include/llvm/Analysis/CFGPrinter.h +++ b/contrib/llvm/include/llvm/Analysis/CFGPrinter.h @@ -150,7 +150,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { /// Display the raw branch weights from PGO. std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I, const Function *F) { - const TerminatorInst *TI = Node->getTerminator(); + const Instruction *TI = Node->getTerminator(); if (TI->getNumSuccessors() == 1) return ""; @@ -172,8 +172,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { // Prepend a 'W' to indicate that this is a weight rather than the actual // profile count (due to scaling). - Twine Attrs = "label=\"W:" + Twine(Weight->getZExtValue()) + "\""; - return Attrs.str(); + return ("label=\"W:" + Twine(Weight->getZExtValue()) + "\"").str(); } }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h b/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h index 5e83ea2a6e2..61b99f6c3e6 100644 --- a/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -364,6 +364,10 @@ public: InvalidSCCSet, nullptr, nullptr, InlinedInternalEdges}; + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation PI = AM.getResult(M); + PreservedAnalyses PA = PreservedAnalyses::all(); CG.buildRefSCCs(); for (auto RCI = CG.postorder_ref_scc_begin(), @@ -428,8 +432,20 @@ public: UR.UpdatedRC = nullptr; UR.UpdatedC = nullptr; + + // Check the PassInstrumentation's BeforePass callbacks before + // running the pass, skip its execution completely if asked to + // (callback returns false). + if (!PI.runBeforePass(Pass, *C)) + continue; + PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR); + if (UR.InvalidatedSCCs.count(C)) + PI.runAfterPassInvalidated(Pass); + else + PI.runAfterPass(Pass, *C); + // Update the SCC and RefSCC if necessary. C = UR.UpdatedC ? UR.UpdatedC : C; RC = UR.UpdatedRC ? UR.UpdatedRC : RC; @@ -615,12 +631,20 @@ public: if (CG.lookupSCC(*N) != CurrentC) continue; - PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM); + Function &F = N->getFunction(); + + PassInstrumentation PI = FAM.getResult(F); + if (!PI.runBeforePass(Pass, F)) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); + + PI.runAfterPass(Pass, F); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. - FAM.invalidate(N->getFunction(), PassPA); + FAM.invalidate(F, PassPA); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -690,6 +714,8 @@ public: PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { PreservedAnalyses PA = PreservedAnalyses::all(); + PassInstrumentation PI = + AM.getResult(InitialC, CG); // The SCC may be refined while we are running passes over it, so set up // a pointer that we can update. @@ -733,8 +759,17 @@ public: auto CallCounts = ScanSCC(*C, CallHandles); for (int Iteration = 0;; ++Iteration) { + + if (!PI.runBeforePass(Pass, *C)) + continue; + PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR); + if (UR.InvalidatedSCCs.count(C)) + PI.runAfterPassInvalidated(Pass); + else + PI.runAfterPass(Pass, *C); + // If the SCC structure has changed, bail immediately and let the outer // CGSCC layer handle any iteration to reflect the refined structure. if (UR.UpdatedC && UR.UpdatedC != C) { diff --git a/contrib/llvm/include/llvm/Analysis/CaptureTracking.h b/contrib/llvm/include/llvm/Analysis/CaptureTracking.h index 7a869a51233..aaaaff9ae25 100644 --- a/contrib/llvm/include/llvm/Analysis/CaptureTracking.h +++ b/contrib/llvm/include/llvm/Analysis/CaptureTracking.h @@ -22,6 +22,14 @@ namespace llvm { class DominatorTree; class OrderedBasicBlock; + /// The default value for MaxUsesToExplore argument. It's relatively small to + /// keep the cost of analysis reasonable for clients like BasicAliasAnalysis, + /// where the results can't be cached. + /// TODO: we should probably introduce a caching CaptureTracking analysis and + /// use it where possible. The caching version can use much higher limit or + /// don't have this cap at all. + unsigned constexpr DefaultMaxUsesToExplore = 20; + /// PointerMayBeCaptured - Return true if this pointer value may be captured /// by the enclosing function (which is required to exist). This routine can /// be expensive, so consider caching the results. The boolean ReturnCaptures @@ -29,9 +37,12 @@ namespace llvm { /// counts as capturing it or not. The boolean StoreCaptures specified /// whether storing the value (or part of it) into memory anywhere /// automatically counts as capturing it or not. + /// MaxUsesToExplore specifies how many uses should the analysis explore for + /// one value before giving up due too "too many uses". bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, - bool StoreCaptures); + bool StoreCaptures, + unsigned MaxUsesToExplore = DefaultMaxUsesToExplore); /// PointerMayBeCapturedBefore - Return true if this pointer value may be /// captured by the enclosing function (which is required to exist). If a @@ -44,10 +55,13 @@ namespace llvm { /// or not. Captures by the provided instruction are considered if the /// final parameter is true. An ordered basic block in \p OBB could be used /// to speed up capture-tracker queries. + /// MaxUsesToExplore specifies how many uses should the analysis explore for + /// one value before giving up due too "too many uses". bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, const DominatorTree *DT, bool IncludeI = false, - OrderedBasicBlock *OBB = nullptr); + OrderedBasicBlock *OBB = nullptr, + unsigned MaxUsesToExplore = DefaultMaxUsesToExplore); /// This callback is used in conjunction with PointerMayBeCaptured. In /// addition to the interface here, you'll need to provide your own getters @@ -75,7 +89,10 @@ namespace llvm { /// PointerMayBeCaptured - Visit the value and the values derived from it and /// find values which appear to be capturing the pointer value. This feeds /// results into and is controlled by the CaptureTracker object. - void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker); + /// MaxUsesToExplore specifies how many uses should the analysis explore for + /// one value before giving up due too "too many uses". + void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker, + unsigned MaxUsesToExplore = DefaultMaxUsesToExplore); } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Analysis/CmpInstAnalysis.h b/contrib/llvm/include/llvm/Analysis/CmpInstAnalysis.h index 3cc69d9fea2..0e9c6a96b0f 100644 --- a/contrib/llvm/include/llvm/Analysis/CmpInstAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/CmpInstAnalysis.h @@ -46,19 +46,18 @@ namespace llvm { /// unsigned getICmpCode(const ICmpInst *ICI, bool InvertPred = false); - /// This is the complement of getICmpCode, which turns an opcode and two - /// operands into either a constant true or false, or the predicate for a new - /// ICmp instruction. The sign is passed in to determine which kind of - /// predicate to use in the new icmp instruction. + /// This is the complement of getICmpCode. It turns a predicate code into + /// either a constant true or false or the predicate for a new ICmp. + /// The sign is passed in to determine which kind of predicate to use in the + /// new ICmp instruction. /// Non-NULL return value will be a true or false constant. - /// NULL return means a new ICmp is needed. The predicate for which is output - /// in NewICmpPred. - Value *getICmpValue(bool Sign, unsigned Code, Value *LHS, Value *RHS, - CmpInst::Predicate &NewICmpPred); + /// NULL return means a new ICmp is needed. The predicate is output in Pred. + Constant *getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy, + CmpInst::Predicate &Pred); /// Return true if both predicates match sign or if at least one of them is an /// equality comparison (which is signless). - bool PredicatesFoldable(CmpInst::Predicate p1, CmpInst::Predicate p2); + bool predicatesFoldable(CmpInst::Predicate P1, CmpInst::Predicate P2); /// Decompose an icmp into the form ((X & Mask) pred 0) if possible. The /// returned predicate is either == or !=. Returns false if decomposition diff --git a/contrib/llvm/include/llvm/Analysis/DemandedBits.h b/contrib/llvm/include/llvm/Analysis/DemandedBits.h index d4384609762..4c4e3f6c99e 100644 --- a/contrib/llvm/include/llvm/Analysis/DemandedBits.h +++ b/contrib/llvm/include/llvm/Analysis/DemandedBits.h @@ -44,19 +44,30 @@ public: F(F), AC(AC), DT(DT) {} /// Return the bits demanded from instruction I. + /// + /// For vector instructions individual vector elements are not distinguished: + /// A bit is demanded if it is demanded for any of the vector elements. The + /// size of the return value corresponds to the type size in bits of the + /// scalar type. + /// + /// Instructions that do not have integer or vector of integer type are + /// accepted, but will always produce a mask with all bits set. APInt getDemandedBits(Instruction *I); /// Return true if, during analysis, I could not be reached. bool isInstructionDead(Instruction *I); + /// Return whether this use is dead by means of not having any demanded bits. + bool isUseDead(Use *U); + void print(raw_ostream &OS); private: void performAnalysis(); void determineLiveOperandBits(const Instruction *UserI, - const Instruction *I, unsigned OperandNo, + const Value *Val, unsigned OperandNo, const APInt &AOut, APInt &AB, - KnownBits &Known, KnownBits &Known2); + KnownBits &Known, KnownBits &Known2, bool &KnownBitsComputed); Function &F; AssumptionCache &AC; @@ -67,6 +78,9 @@ private: // The set of visited instructions (non-integer-typed only). SmallPtrSet Visited; DenseMap AliveBits; + // Uses with no demanded bits. If the user also has no demanded bits, the use + // might not be stored explicitly in this map, to save memory during analysis. + SmallPtrSet DeadUses; }; class DemandedBitsWrapperPass : public FunctionPass { diff --git a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h index c8ec737a2cb..69d0e2c1513 100644 --- a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h @@ -936,6 +936,17 @@ template class ArrayRef; friend struct AnalysisInfoMixin; }; // class DependenceAnalysis + /// Printer pass to dump DA results. + struct DependenceAnalysisPrinterPass + : public PassInfoMixin { + DependenceAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); + + private: + raw_ostream &OS; + }; // class DependenceAnalysisPrinterPass + /// Legacy pass manager pass to access dependence information class DependenceAnalysisWrapperPass : public FunctionPass { public: diff --git a/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h index 328c8645d3c..d834862db09 100644 --- a/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h @@ -7,55 +7,199 @@ // //===----------------------------------------------------------------------===// // -// The divergence analysis is an LLVM pass which can be used to find out -// if a branch instruction in a GPU program is divergent or not. It can help -// branch optimizations such as jump threading and loop unswitching to make -// better decisions. +// \file +// The divergence analysis determines which instructions and branches are +// divergent given a set of divergent source instructions. // //===----------------------------------------------------------------------===// + #ifndef LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H #define LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H #include "llvm/ADT/DenseSet.h" +#include "llvm/Analysis/SyncDependenceAnalysis.h" #include "llvm/IR/Function.h" #include "llvm/Pass.h" +#include namespace llvm { +class Module; class Value; -class DivergenceAnalysis : public FunctionPass { +class Instruction; +class Loop; +class raw_ostream; +class TargetTransformInfo; + +/// \brief Generic divergence analysis for reducible CFGs. +/// +/// This analysis propagates divergence in a data-parallel context from sources +/// of divergence to all users. It requires reducible CFGs. All assignments +/// should be in SSA form. +class DivergenceAnalysis { public: - static char ID; + /// \brief This instance will analyze the whole function \p F or the loop \p + /// RegionLoop. + /// + /// \param RegionLoop if non-null the analysis is restricted to \p RegionLoop. + /// Otherwise the whole function is analyzed. + /// \param IsLCSSAForm whether the analysis may assume that the IR in the + /// region in in LCSSA form. + DivergenceAnalysis(const Function &F, const Loop *RegionLoop, + const DominatorTree &DT, const LoopInfo &LI, + SyncDependenceAnalysis &SDA, bool IsLCSSAForm); - DivergenceAnalysis() : FunctionPass(ID) { - initializeDivergenceAnalysisPass(*PassRegistry::getPassRegistry()); - } + /// \brief The loop that defines the analyzed region (if any). + const Loop *getRegionLoop() const { return RegionLoop; } + const Function &getFunction() const { return F; } - void getAnalysisUsage(AnalysisUsage &AU) const override; + /// \brief Whether \p BB is part of the region. + bool inRegion(const BasicBlock &BB) const; + /// \brief Whether \p I is part of the region. + bool inRegion(const Instruction &I) const; - bool runOnFunction(Function &F) override; + /// \brief Mark \p UniVal as a value that is always uniform. + void addUniformOverride(const Value &UniVal); - // Print all divergent branches in the function. - void print(raw_ostream &OS, const Module *) const override; + /// \brief Mark \p DivVal as a value that is always divergent. + void markDivergent(const Value &DivVal); - // Returns true if V is divergent at its definition. - // - // Even if this function returns false, V may still be divergent when used - // in a different basic block. - bool isDivergent(const Value *V) const { return DivergentValues.count(V); } + /// \brief Propagate divergence to all instructions in the region. + /// Divergence is seeded by calls to \p markDivergent. + void compute(); - // Returns true if V is uniform/non-divergent. - // - // Even if this function returns true, V may still be divergent when used - // in a different basic block. - bool isUniform(const Value *V) const { return !isDivergent(V); } + /// \brief Whether any value was marked or analyzed to be divergent. + bool hasDetectedDivergence() const { return !DivergentValues.empty(); } - // Keep the analysis results uptodate by removing an erased value. - void removeValue(const Value *V) { DivergentValues.erase(V); } + /// \brief Whether \p Val will always return a uniform value regardless of its + /// operands + bool isAlwaysUniform(const Value &Val) const; + + /// \brief Whether \p Val is a divergent value + bool isDivergent(const Value &Val) const; + + void print(raw_ostream &OS, const Module *) const; private: - // Stores all divergent values. - DenseSet DivergentValues; -}; -} // End llvm namespace + bool updateTerminator(const Instruction &Term) const; + bool updatePHINode(const PHINode &Phi) const; -#endif //LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H \ No newline at end of file + /// \brief Computes whether \p Inst is divergent based on the + /// divergence of its operands. + /// + /// \returns Whether \p Inst is divergent. + /// + /// This should only be called for non-phi, non-terminator instructions. + bool updateNormalInstruction(const Instruction &Inst) const; + + /// \brief Mark users of live-out users as divergent. + /// + /// \param LoopHeader the header of the divergent loop. + /// + /// Marks all users of live-out values of the loop headed by \p LoopHeader + /// as divergent and puts them on the worklist. + void taintLoopLiveOuts(const BasicBlock &LoopHeader); + + /// \brief Push all users of \p Val (in the region) to the worklist + void pushUsers(const Value &I); + + /// \brief Push all phi nodes in @block to the worklist + void pushPHINodes(const BasicBlock &Block); + + /// \brief Mark \p Block as join divergent + /// + /// A block is join divergent if two threads may reach it from different + /// incoming blocks at the same time. + void markBlockJoinDivergent(const BasicBlock &Block) { + DivergentJoinBlocks.insert(&Block); + } + + /// \brief Whether \p Val is divergent when read in \p ObservingBlock. + bool isTemporalDivergent(const BasicBlock &ObservingBlock, + const Value &Val) const; + + /// \brief Whether \p Block is join divergent + /// + /// (see markBlockJoinDivergent). + bool isJoinDivergent(const BasicBlock &Block) const { + return DivergentJoinBlocks.find(&Block) != DivergentJoinBlocks.end(); + } + + /// \brief Propagate control-induced divergence to users (phi nodes and + /// instructions). + // + // \param JoinBlock is a divergent loop exit or join point of two disjoint + // paths. + // \returns Whether \p JoinBlock is a divergent loop exit of \p TermLoop. + bool propagateJoinDivergence(const BasicBlock &JoinBlock, + const Loop *TermLoop); + + /// \brief Propagate induced value divergence due to control divergence in \p + /// Term. + void propagateBranchDivergence(const Instruction &Term); + + /// \brief Propagate divergent caused by a divergent loop exit. + /// + /// \param ExitingLoop is a divergent loop. + void propagateLoopDivergence(const Loop &ExitingLoop); + +private: + const Function &F; + // If regionLoop != nullptr, analysis is only performed within \p RegionLoop. + // Otw, analyze the whole function + const Loop *RegionLoop; + + const DominatorTree &DT; + const LoopInfo &LI; + + // Recognized divergent loops + DenseSet DivergentLoops; + + // The SDA links divergent branches to divergent control-flow joins. + SyncDependenceAnalysis &SDA; + + // Use simplified code path for LCSSA form. + bool IsLCSSAForm; + + // Set of known-uniform values. + DenseSet UniformOverrides; + + // Blocks with joining divergent control from different predecessors. + DenseSet DivergentJoinBlocks; + + // Detected/marked divergent values. + DenseSet DivergentValues; + + // Internal worklist for divergence propagation. + std::vector Worklist; +}; + +/// \brief Divergence analysis frontend for GPU kernels. +class GPUDivergenceAnalysis { + SyncDependenceAnalysis SDA; + DivergenceAnalysis DA; + +public: + /// Runs the divergence analysis on @F, a GPU kernel + GPUDivergenceAnalysis(Function &F, const DominatorTree &DT, + const PostDominatorTree &PDT, const LoopInfo &LI, + const TargetTransformInfo &TTI); + + /// Whether any divergence was detected. + bool hasDivergence() const { return DA.hasDetectedDivergence(); } + + /// The GPU kernel this analysis result is for + const Function &getFunction() const { return DA.getFunction(); } + + /// Whether \p V is divergent. + bool isDivergent(const Value &V) const; + + /// Whether \p V is uniform/non-divergent + bool isUniform(const Value &V) const { return !isDivergent(V); } + + /// Print all divergent values in the kernel. + void print(raw_ostream &OS, const Module *) const; +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H diff --git a/contrib/llvm/include/llvm/Analysis/GlobalsModRef.h b/contrib/llvm/include/llvm/Analysis/GlobalsModRef.h index 09cef68ce70..3a664ca6ef5 100644 --- a/contrib/llvm/include/llvm/Analysis/GlobalsModRef.h +++ b/contrib/llvm/include/llvm/Analysis/GlobalsModRef.h @@ -88,7 +88,7 @@ public: AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); using AAResultBase::getModRefInfo; - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); /// getModRefBehavior - Return the behavior of the specified function if /// called from the specified call site. The call site may be null in which @@ -98,7 +98,7 @@ public: /// getModRefBehavior - Return the behavior of the specified function if /// called from the specified call site. The call site may be null in which /// case the most generic behavior of this function should be returned. - FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS); + FunctionModRefBehavior getModRefBehavior(const CallBase *Call); private: FunctionInfo *getFunctionInfo(const Function *F); @@ -113,7 +113,7 @@ private: void CollectSCCMembership(CallGraph &CG); bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V); - ModRefInfo getModRefInfoForArgument(ImmutableCallSite CS, + ModRefInfo getModRefInfoForArgument(const CallBase *Call, const GlobalValue *GV); }; diff --git a/contrib/llvm/include/llvm/Analysis/GuardUtils.h b/contrib/llvm/include/llvm/Analysis/GuardUtils.h new file mode 100644 index 00000000000..3b151eeafc8 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/GuardUtils.h @@ -0,0 +1,26 @@ +//===-- GuardUtils.h - Utils for work with guards ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Utils that are used to perform analyzes related to guards and their +// conditions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_GUARDUTILS_H +#define LLVM_ANALYSIS_GUARDUTILS_H + +namespace llvm { + +class User; + +/// Returns true iff \p U has semantics of a guard. +bool isGuard(const User *U); + +} // llvm + +#endif // LLVM_ANALYSIS_GUARDUTILS_H + diff --git a/contrib/llvm/include/llvm/Analysis/IVDescriptors.h b/contrib/llvm/include/llvm/Analysis/IVDescriptors.h new file mode 100644 index 00000000000..64b4ae23cc5 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/IVDescriptors.h @@ -0,0 +1,357 @@ +//===- llvm/Analysis/IVDescriptors.h - IndVar Descriptors -------*- 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" induction and recurrence variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IVDESCRIPTORS_H +#define LLVM_ANALYSIS_IVDESCRIPTORS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DemandedBits.h" +#include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/MustExecute.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class AliasSet; +class AliasSetTracker; +class BasicBlock; +class DataLayout; +class Loop; +class LoopInfo; +class OptimizationRemarkEmitter; +class PredicatedScalarEvolution; +class PredIteratorCache; +class ScalarEvolution; +class SCEV; +class TargetLibraryInfo; +class TargetTransformInfo; + +/// The RecurrenceDescriptor is used to identify recurrences variables in a +/// loop. Reduction is a special case of recurrence that has uses of the +/// recurrence variable outside the loop. The method isReductionPHI identifies +/// reductions that are basic recurrences. +/// +/// Basic recurrences are defined as the summation, product, OR, AND, XOR, min, +/// or max of a set of terms. For example: for(i=0; i &CI) + : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK), + UnsafeAlgebraInst(UAI), RecurrenceType(RT), IsSigned(Signed) { + CastInsts.insert(CI.begin(), CI.end()); + } + + /// This POD struct holds information about a potential recurrence operation. + class InstDesc { + public: + InstDesc(bool IsRecur, Instruction *I, Instruction *UAI = nullptr) + : IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid), + UnsafeAlgebraInst(UAI) {} + + InstDesc(Instruction *I, MinMaxRecurrenceKind K, Instruction *UAI = nullptr) + : IsRecurrence(true), PatternLastInst(I), MinMaxKind(K), + UnsafeAlgebraInst(UAI) {} + + bool isRecurrence() { return IsRecurrence; } + + bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } + + Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } + + MinMaxRecurrenceKind getMinMaxKind() { return MinMaxKind; } + + Instruction *getPatternInst() { return PatternLastInst; } + + private: + // Is this instruction a recurrence candidate. + bool IsRecurrence; + // The last instruction in a min/max pattern (select of the select(icmp()) + // pattern), or the current recurrence instruction otherwise. + Instruction *PatternLastInst; + // If this is a min/max pattern the comparison predicate. + MinMaxRecurrenceKind MinMaxKind; + // Recurrence has unsafe algebra. + Instruction *UnsafeAlgebraInst; + }; + + /// Returns a struct describing if the instruction 'I' can be a recurrence + /// variable of type 'Kind'. If the recurrence is a min/max pattern of + /// select(icmp()) this function advances the instruction pointer 'I' from the + /// compare instruction to the select instruction and stores this pointer in + /// 'PatternLastInst' member of the returned struct. + static InstDesc isRecurrenceInstr(Instruction *I, RecurrenceKind Kind, + InstDesc &Prev, bool HasFunNoNaNAttr); + + /// Returns true if instruction I has multiple uses in Insts + static bool hasMultipleUsesOf(Instruction *I, + SmallPtrSetImpl &Insts, + unsigned MaxNumUses); + + /// Returns true if all uses of the instruction I is within the Set. + static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl &Set); + + /// Returns a struct describing if the instruction if the instruction is a + /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y) + /// or max(X, Y). + static InstDesc isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev); + + /// Returns a struct describing if the instruction is a + /// Select(FCmp(X, Y), (Z = X op PHINode), PHINode) instruction pattern. + static InstDesc isConditionalRdxPattern(RecurrenceKind Kind, Instruction *I); + + /// Returns identity corresponding to the RecurrenceKind. + static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp); + + /// Returns the opcode of binary operation corresponding to the + /// RecurrenceKind. + static unsigned getRecurrenceBinOp(RecurrenceKind Kind); + + /// Returns true if Phi is a reduction of type Kind and adds it to the + /// RecurrenceDescriptor. If either \p DB is non-null or \p AC and \p DT are + /// non-null, the minimal bit width needed to compute the reduction will be + /// computed. + static bool AddReductionVar(PHINode *Phi, RecurrenceKind Kind, Loop *TheLoop, + bool HasFunNoNaNAttr, + RecurrenceDescriptor &RedDes, + DemandedBits *DB = nullptr, + AssumptionCache *AC = nullptr, + DominatorTree *DT = nullptr); + + /// Returns true if Phi is a reduction in TheLoop. The RecurrenceDescriptor + /// is returned in RedDes. If either \p DB is non-null or \p AC and \p DT are + /// non-null, the minimal bit width needed to compute the reduction will be + /// computed. + static bool isReductionPHI(PHINode *Phi, Loop *TheLoop, + RecurrenceDescriptor &RedDes, + DemandedBits *DB = nullptr, + AssumptionCache *AC = nullptr, + DominatorTree *DT = nullptr); + + /// Returns true if Phi is a first-order recurrence. A first-order recurrence + /// is a non-reduction recurrence relation in which the value of the + /// recurrence in the current loop iteration equals a value defined in the + /// previous iteration. \p SinkAfter includes pairs of instructions where the + /// first will be rescheduled to appear after the second if/when the loop is + /// vectorized. It may be augmented with additional pairs if needed in order + /// to handle Phi as a first-order recurrence. + static bool + isFirstOrderRecurrence(PHINode *Phi, Loop *TheLoop, + DenseMap &SinkAfter, + DominatorTree *DT); + + RecurrenceKind getRecurrenceKind() { return Kind; } + + MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; } + + TrackingVH getRecurrenceStartValue() { return StartValue; } + + Instruction *getLoopExitInstr() { return LoopExitInstr; } + + /// Returns true if the recurrence has unsafe algebra which requires a relaxed + /// floating-point model. + bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } + + /// Returns first unsafe algebra instruction in the PHI node's use-chain. + Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } + + /// Returns true if the recurrence kind is an integer kind. + static bool isIntegerRecurrenceKind(RecurrenceKind Kind); + + /// Returns true if the recurrence kind is a floating point kind. + static bool isFloatingPointRecurrenceKind(RecurrenceKind Kind); + + /// Returns true if the recurrence kind is an arithmetic kind. + static bool isArithmeticRecurrenceKind(RecurrenceKind Kind); + + /// Returns the type of the recurrence. This type can be narrower than the + /// actual type of the Phi if the recurrence has been type-promoted. + Type *getRecurrenceType() { return RecurrenceType; } + + /// Returns a reference to the instructions used for type-promoting the + /// recurrence. + SmallPtrSet &getCastInsts() { return CastInsts; } + + /// Returns true if all source operands of the recurrence are SExtInsts. + bool isSigned() { return IsSigned; } + +private: + // The starting value of the recurrence. + // It does not have to be zero! + TrackingVH StartValue; + // The instruction who's value is used outside the loop. + Instruction *LoopExitInstr = nullptr; + // The kind of the recurrence. + RecurrenceKind Kind = RK_NoRecurrence; + // If this a min/max recurrence the kind of recurrence. + MinMaxRecurrenceKind MinMaxKind = MRK_Invalid; + // First occurrence of unasfe algebra in the PHI's use-chain. + Instruction *UnsafeAlgebraInst = nullptr; + // The type of the recurrence. + Type *RecurrenceType = nullptr; + // True if all source operands of the recurrence are SExtInsts. + bool IsSigned = false; + // Instructions used for type-promoting the recurrence. + SmallPtrSet CastInsts; +}; + +/// A struct for saving information about induction variables. +class InductionDescriptor { +public: + /// This enum represents the kinds of inductions that we support. + enum InductionKind { + IK_NoInduction, ///< Not an induction variable. + IK_IntInduction, ///< Integer induction variable. Step = C. + IK_PtrInduction, ///< Pointer induction var. Step = C / sizeof(elem). + IK_FpInduction ///< Floating point induction variable. + }; + +public: + /// Default constructor - creates an invalid induction. + InductionDescriptor() = default; + + /// Get the consecutive direction. Returns: + /// 0 - unknown or non-consecutive. + /// 1 - consecutive and increasing. + /// -1 - consecutive and decreasing. + int getConsecutiveDirection() const; + + Value *getStartValue() const { return StartValue; } + InductionKind getKind() const { return IK; } + const SCEV *getStep() const { return Step; } + BinaryOperator *getInductionBinOp() const { return InductionBinOp; } + ConstantInt *getConstIntStepValue() const; + + /// Returns true if \p Phi is an induction in the loop \p L. If \p Phi is an + /// induction, the induction descriptor \p D will contain the data describing + /// this induction. If by some other means the caller has a better SCEV + /// expression for \p Phi than the one returned by the ScalarEvolution + /// analysis, it can be passed through \p Expr. If the def-use chain + /// associated with the phi includes casts (that we know we can ignore + /// under proper runtime checks), they are passed through \p CastsToIgnore. + static bool + isInductionPHI(PHINode *Phi, const Loop *L, ScalarEvolution *SE, + InductionDescriptor &D, const SCEV *Expr = nullptr, + SmallVectorImpl *CastsToIgnore = nullptr); + + /// Returns true if \p Phi is a floating point induction in the loop \p L. + /// If \p Phi is an induction, the induction descriptor \p D will contain + /// the data describing this induction. + static bool isFPInductionPHI(PHINode *Phi, const Loop *L, ScalarEvolution *SE, + InductionDescriptor &D); + + /// Returns true if \p Phi is a loop \p L induction, in the context associated + /// with the run-time predicate of PSE. If \p Assume is true, this can add + /// further SCEV predicates to \p PSE in order to prove that \p Phi is an + /// induction. + /// If \p Phi is an induction, \p D will contain the data describing this + /// induction. + static bool isInductionPHI(PHINode *Phi, const Loop *L, + PredicatedScalarEvolution &PSE, + InductionDescriptor &D, bool Assume = false); + + /// Returns true if the induction type is FP and the binary operator does + /// not have the "fast-math" property. Such operation requires a relaxed FP + /// mode. + bool hasUnsafeAlgebra() { + return InductionBinOp && !cast(InductionBinOp)->isFast(); + } + + /// Returns induction operator that does not have "fast-math" property + /// and requires FP unsafe mode. + Instruction *getUnsafeAlgebraInst() { + if (!InductionBinOp || cast(InductionBinOp)->isFast()) + return nullptr; + return InductionBinOp; + } + + /// Returns binary opcode of the induction operator. + Instruction::BinaryOps getInductionOpcode() const { + return InductionBinOp ? InductionBinOp->getOpcode() + : Instruction::BinaryOpsEnd; + } + + /// Returns a reference to the type cast instructions in the induction + /// update chain, that are redundant when guarded with a runtime + /// SCEV overflow check. + const SmallVectorImpl &getCastInsts() const { + return RedundantCasts; + } + +private: + /// Private constructor - used by \c isInductionPHI. + InductionDescriptor(Value *Start, InductionKind K, const SCEV *Step, + BinaryOperator *InductionBinOp = nullptr, + SmallVectorImpl *Casts = nullptr); + + /// Start value. + TrackingVH StartValue; + /// Induction kind. + InductionKind IK = IK_NoInduction; + /// Step value. + const SCEV *Step = nullptr; + // Instruction that advances induction variable. + BinaryOperator *InductionBinOp = nullptr; + // Instructions used for type-casts of the induction variable, + // that are redundant when guarded with a runtime SCEV overflow check. + SmallVector RedundantCasts; +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_IVDESCRIPTORS_H diff --git a/contrib/llvm/include/llvm/Analysis/IndirectCallSiteVisitor.h b/contrib/llvm/include/llvm/Analysis/IndirectCallSiteVisitor.h deleted file mode 100644 index dde56a143c5..00000000000 --- a/contrib/llvm/include/llvm/Analysis/IndirectCallSiteVisitor.h +++ /dev/null @@ -1,35 +0,0 @@ -//===-- IndirectCallSiteVisitor.h - indirect call-sites visitor -----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements defines a visitor class and a helper function that find -// all indirect call-sites in a function. - -#include "llvm/IR/InstVisitor.h" -#include - -namespace llvm { -// Visitor class that finds all indirect call sites. -struct PGOIndirectCallSiteVisitor - : public InstVisitor { - std::vector IndirectCallInsts; - PGOIndirectCallSiteVisitor() {} - - void visitCallSite(CallSite CS) { - if (CS.isIndirectCall()) - IndirectCallInsts.push_back(CS.getInstruction()); - } -}; - -// Helper function that finds all indirect call sites. -inline std::vector findIndirectCallSites(Function &F) { - PGOIndirectCallSiteVisitor ICV; - ICV.visit(F); - return ICV.IndirectCallInsts; -} -} diff --git a/contrib/llvm/include/llvm/Analysis/IndirectCallVisitor.h b/contrib/llvm/include/llvm/Analysis/IndirectCallVisitor.h new file mode 100644 index 00000000000..d00cf63368f --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/IndirectCallVisitor.h @@ -0,0 +1,39 @@ +//===-- IndirectCallVisitor.h - indirect call visitor ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements defines a visitor class and a helper function that find +// all indirect call-sites in a function. + +#ifndef LLVM_ANALYSIS_INDIRECTCALLVISITOR_H +#define LLVM_ANALYSIS_INDIRECTCALLVISITOR_H + +#include "llvm/IR/InstVisitor.h" +#include + +namespace llvm { +// Visitor class that finds all indirect call. +struct PGOIndirectCallVisitor : public InstVisitor { + std::vector IndirectCalls; + PGOIndirectCallVisitor() {} + + void visitCallBase(CallBase &Call) { + if (Call.isIndirectCall()) + IndirectCalls.push_back(&Call); + } +}; + +// Helper function that finds all indirect call sites. +inline std::vector findIndirectCalls(Function &F) { + PGOIndirectCallVisitor ICV; + ICV.visit(F); + return ICV.IndirectCalls; +} +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/InlineCost.h b/contrib/llvm/include/llvm/Analysis/InlineCost.h index 8c412057fb8..4c270354b0c 100644 --- a/contrib/llvm/include/llvm/Analysis/InlineCost.h +++ b/contrib/llvm/include/llvm/Analysis/InlineCost.h @@ -46,7 +46,6 @@ const int IndirectCallThreshold = 100; const int CallPenalty = 25; const int LastCallToStaticBonus = 15000; const int ColdccPenalty = 2000; -const int NoreturnPenalty = 10000; /// Do not inline functions which allocate this many bytes on the stack /// when the caller is recursive. const unsigned TotalAllocaSizeRecursiveCaller = 1024; @@ -74,8 +73,15 @@ class InlineCost { /// The adjusted threshold against which this cost was computed. const int Threshold; + /// Must be set for Always and Never instances. + const char *Reason = nullptr; + // Trivial constructor, interesting logic in the factory functions below. - InlineCost(int Cost, int Threshold) : Cost(Cost), Threshold(Threshold) {} + InlineCost(int Cost, int Threshold, const char *Reason = nullptr) + : Cost(Cost), Threshold(Threshold), Reason(Reason) { + assert((isVariable() || Reason) && + "Reason must be provided for Never or Always"); + } public: static InlineCost get(int Cost, int Threshold) { @@ -83,11 +89,11 @@ public: assert(Cost < NeverInlineCost && "Cost crosses sentinel value"); return InlineCost(Cost, Threshold); } - static InlineCost getAlways() { - return InlineCost(AlwaysInlineCost, 0); + static InlineCost getAlways(const char *Reason) { + return InlineCost(AlwaysInlineCost, 0, Reason); } - static InlineCost getNever() { - return InlineCost(NeverInlineCost, 0); + static InlineCost getNever(const char *Reason) { + return InlineCost(NeverInlineCost, 0, Reason); } /// Test whether the inline cost is low enough for inlining. @@ -112,12 +118,30 @@ public: return Threshold; } + /// Get the reason of Always or Never. + const char *getReason() const { + assert((Reason || isVariable()) && + "InlineCost reason must be set for Always or Never"); + return Reason; + } + /// Get the cost delta from the threshold for inlining. /// Only valid if the cost is of the variable kind. Returns a negative /// value if the cost is too high to inline. int getCostDelta() const { return Threshold - getCost(); } }; +/// InlineResult is basically true or false. For false results the message +/// describes a reason why it is decided not to inline. +struct InlineResult { + const char *message = nullptr; + InlineResult(bool result, const char *message = nullptr) + : message(result ? nullptr : (message ? message : "cost > threshold")) {} + InlineResult(const char *message = nullptr) : message(message) {} + operator bool() const { return !message; } + operator const char *() const { return message; } +}; + /// Thresholds to tune inline cost analysis. The inline cost analysis decides /// the condition to apply a threshold and applies it. Otherwise, /// DefaultThreshold is used. If a threshold is Optional, it is applied only diff --git a/contrib/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h b/contrib/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h new file mode 100644 index 00000000000..073e6ec3b7f --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h @@ -0,0 +1,150 @@ +//===-- InstructionPrecedenceTracking.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Implements a class that is able to define some instructions as "special" +// (e.g. as having implicit control flow, or writing memory, or having another +// interesting property) and then efficiently answers queries of the types: +// 1. Are there any special instructions in the block of interest? +// 2. Return first of the special instructions in the given block; +// 3. Check if the given instruction is preceeded by the first special +// instruction in the same block. +// The class provides caching that allows to answer these queries quickly. The +// user must make sure that the cached data is invalidated properly whenever +// a content of some tracked block is changed. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H +#define LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H + +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/OrderedInstructions.h" + +namespace llvm { + +class InstructionPrecedenceTracking { + // Maps a block to the topmost special instruction in it. If the value is + // nullptr, it means that it is known that this block does not contain any + // special instructions. + DenseMap FirstSpecialInsts; + // Allows to answer queries about precedence of instructions within one block. + OrderedInstructions OI; + + // Fills information about the given block's special instructions. + void fill(const BasicBlock *BB); + +#ifndef NDEBUG + /// Asserts that the cached info for \p BB is up-to-date. This helps to catch + /// the usage error of accessing a block without properly invalidating after a + /// previous transform. + void validate(const BasicBlock *BB) const; + + /// Asserts whether or not the contents of this tracking is up-to-date. This + /// helps to catch the usage error of accessing a block without properly + /// invalidating after a previous transform. + void validateAll() const; +#endif + +protected: + InstructionPrecedenceTracking(DominatorTree *DT) + : OI(OrderedInstructions(DT)) {} + + /// Returns the topmost special instruction from the block \p BB. Returns + /// nullptr if there is no special instructions in the block. + const Instruction *getFirstSpecialInstruction(const BasicBlock *BB); + + /// Returns true iff at least one instruction from the basic block \p BB is + /// special. + bool hasSpecialInstructions(const BasicBlock *BB); + + /// Returns true iff the first special instruction of \p Insn's block exists + /// and dominates \p Insn. + bool isPreceededBySpecialInstruction(const Instruction *Insn); + + /// A predicate that defines whether or not the instruction \p Insn is + /// considered special and needs to be tracked. Implementing this method in + /// children classes allows to implement tracking of implicit control flow, + /// memory writing instructions or any other kinds of instructions we might + /// be interested in. + virtual bool isSpecialInstruction(const Instruction *Insn) const = 0; + + virtual ~InstructionPrecedenceTracking() = default; + +public: + /// Notifies this tracking that we are going to insert a new instruction \p + /// Inst to the basic block \p BB. It makes all necessary updates to internal + /// caches to keep them consistent. + void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB); + + /// Notifies this tracking that we are going to remove the instruction \p Inst + /// It makes all necessary updates to internal caches to keep them consistent. + void removeInstruction(const Instruction *Inst); + + /// Invalidates all information from this tracking. + void clear(); +}; + +/// This class allows to keep track on instructions with implicit control flow. +/// These are instructions that may not pass execution to their successors. For +/// example, throwing calls and guards do not always do this. If we need to know +/// for sure that some instruction is guaranteed to execute if the given block +/// is reached, then we need to make sure that there is no implicit control flow +/// instruction (ICFI) preceeding it. For example, this check is required if we +/// perform PRE moving non-speculable instruction to other place. +class ImplicitControlFlowTracking : public InstructionPrecedenceTracking { +public: + ImplicitControlFlowTracking(DominatorTree *DT) + : InstructionPrecedenceTracking(DT) {} + + /// Returns the topmost instruction with implicit control flow from the given + /// basic block. Returns nullptr if there is no such instructions in the block. + const Instruction *getFirstICFI(const BasicBlock *BB) { + return getFirstSpecialInstruction(BB); + } + + /// Returns true if at least one instruction from the given basic block has + /// implicit control flow. + bool hasICF(const BasicBlock *BB) { + return hasSpecialInstructions(BB); + } + + /// Returns true if the first ICFI of Insn's block exists and dominates Insn. + bool isDominatedByICFIFromSameBlock(const Instruction *Insn) { + return isPreceededBySpecialInstruction(Insn); + } + + virtual bool isSpecialInstruction(const Instruction *Insn) const; +}; + +class MemoryWriteTracking : public InstructionPrecedenceTracking { +public: + MemoryWriteTracking(DominatorTree *DT) : InstructionPrecedenceTracking(DT) {} + + /// Returns the topmost instruction that may write memory from the given + /// basic block. Returns nullptr if there is no such instructions in the block. + const Instruction *getFirstMemoryWrite(const BasicBlock *BB) { + return getFirstSpecialInstruction(BB); + } + + /// Returns true if at least one instruction from the given basic block may + /// write memory. + bool mayWriteToMemory(const BasicBlock *BB) { + return hasSpecialInstructions(BB); + } + + /// Returns true if the first memory writing instruction of Insn's block + /// exists and dominates Insn. + bool isDominatedByMemoryWriteFromSameBlock(const Instruction *Insn) { + return isPreceededBySpecialInstruction(Insn); + } + + virtual bool isSpecialInstruction(const Instruction *Insn) const; +}; + +} // llvm + +#endif // LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H diff --git a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h index 4f896bddff8..6662e91037e 100644 --- a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -32,6 +32,8 @@ #ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H #define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/User.h" namespace llvm { @@ -40,7 +42,6 @@ template class AnalysisManager; template class ArrayRef; class AssumptionCache; class DominatorTree; -class Instruction; class ImmutableCallSite; class DataLayout; class FastMathFlags; @@ -50,6 +51,41 @@ class Pass; class TargetLibraryInfo; class Type; class Value; +class MDNode; +class BinaryOperator; + +/// InstrInfoQuery provides an interface to query additional information for +/// instructions like metadata or keywords like nsw, which provides conservative +/// results if the users specified it is safe to use. +struct InstrInfoQuery { + InstrInfoQuery(bool UMD) : UseInstrInfo(UMD) {} + InstrInfoQuery() : UseInstrInfo(true) {} + bool UseInstrInfo = true; + + MDNode *getMetadata(const Instruction *I, unsigned KindID) const { + if (UseInstrInfo) + return I->getMetadata(KindID); + return nullptr; + } + + template bool hasNoUnsignedWrap(const InstT *Op) const { + if (UseInstrInfo) + return Op->hasNoUnsignedWrap(); + return false; + } + + template bool hasNoSignedWrap(const InstT *Op) const { + if (UseInstrInfo) + return Op->hasNoSignedWrap(); + return false; + } + + bool isExact(const BinaryOperator *Op) const { + if (UseInstrInfo && isa(Op)) + return cast(Op)->isExact(); + return false; + } +}; struct SimplifyQuery { const DataLayout &DL; @@ -58,14 +94,19 @@ struct SimplifyQuery { AssumptionCache *AC = nullptr; const Instruction *CxtI = nullptr; + // Wrapper to query additional information for instructions like metadata or + // keywords like nsw, which provides conservative results if those cannot + // be safely used. + const InstrInfoQuery IIQ; + SimplifyQuery(const DataLayout &DL, const Instruction *CXTI = nullptr) : DL(DL), CxtI(CXTI) {} SimplifyQuery(const DataLayout &DL, const TargetLibraryInfo *TLI, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, - const Instruction *CXTI = nullptr) - : DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI) {} + const Instruction *CXTI = nullptr, bool UseInstrInfo = true) + : DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), IIQ(UseInstrInfo) {} SimplifyQuery getWithInstruction(Instruction *I) const { SimplifyQuery Copy(*this); Copy.CxtI = I; diff --git a/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h b/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h index 6b195073324..3083db75b81 100644 --- a/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h +++ b/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// +/// \file /// Compute iterated dominance frontiers using a linear time algorithm. /// /// The algorithm used here is based on: @@ -28,6 +28,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFGDiff.h" #include "llvm/IR/Dominators.h" namespace llvm { @@ -45,17 +46,21 @@ namespace llvm { template class IDFCalculator { public: - IDFCalculator(DominatorTreeBase &DT) - : DT(DT), useLiveIn(false) {} + IDFCalculator(DominatorTreeBase &DT) + : DT(DT), GD(nullptr), useLiveIn(false) {} - /// Give the IDF calculator the set of blocks in which the value is - /// defined. This is equivalent to the set of starting blocks it should be - /// calculating the IDF for (though later gets pruned based on liveness). - /// - /// Note: This set *must* live for the entire lifetime of the IDF calculator. - void setDefiningBlocks(const SmallPtrSetImpl &Blocks) { - DefBlocks = &Blocks; - } + IDFCalculator(DominatorTreeBase &DT, + const GraphDiff *GD) + : DT(DT), GD(GD), useLiveIn(false) {} + + /// Give the IDF calculator the set of blocks in which the value is + /// defined. This is equivalent to the set of starting blocks it should be + /// calculating the IDF for (though later gets pruned based on liveness). + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + void setDefiningBlocks(const SmallPtrSetImpl &Blocks) { + DefBlocks = &Blocks; + } /// Give the IDF calculator the set of blocks in which the value is /// live on entry to the block. This is used to prune the IDF calculation to @@ -85,6 +90,7 @@ class IDFCalculator { private: DominatorTreeBase &DT; + const GraphDiff *GD; bool useLiveIn; const SmallPtrSetImpl *LiveInBlocks; const SmallPtrSetImpl *DefBlocks; diff --git a/contrib/llvm/include/llvm/Analysis/LegacyDivergenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/LegacyDivergenceAnalysis.h new file mode 100644 index 00000000000..fc426ad7fb6 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/LegacyDivergenceAnalysis.h @@ -0,0 +1,69 @@ +//===- llvm/Analysis/LegacyDivergenceAnalysis.h - KernelDivergence Analysis -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The kernel divergence analysis is an LLVM pass which can be used to find out +// if a branch instruction in a GPU program (kernel) is divergent or not. It can help +// branch optimizations such as jump threading and loop unswitching to make +// better decisions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H +#define LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/DivergenceAnalysis.h" + +namespace llvm { +class Value; +class GPUDivergenceAnalysis; +class LegacyDivergenceAnalysis : public FunctionPass { +public: + static char ID; + + LegacyDivergenceAnalysis() : FunctionPass(ID) { + initializeLegacyDivergenceAnalysisPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnFunction(Function &F) override; + + // Print all divergent branches in the function. + void print(raw_ostream &OS, const Module *) const override; + + // Returns true if V is divergent at its definition. + // + // Even if this function returns false, V may still be divergent when used + // in a different basic block. + bool isDivergent(const Value *V) const; + + // Returns true if V is uniform/non-divergent. + // + // Even if this function returns true, V may still be divergent when used + // in a different basic block. + bool isUniform(const Value *V) const { return !isDivergent(V); } + + // Keep the analysis results uptodate by removing an erased value. + void removeValue(const Value *V) { DivergentValues.erase(V); } + +private: + // Whether analysis should be performed by GPUDivergenceAnalysis. + bool shouldUseGPUDivergenceAnalysis(const Function &F) const; + + // (optional) handle to new DivergenceAnalysis + std::unique_ptr gpuDA; + + // Stores all divergent values. + DenseSet DivergentValues; +}; +} // End llvm namespace + +#endif //LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H diff --git a/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h index d27b3e42bbe..4ed00e20775 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h @@ -97,6 +97,19 @@ public: /// Set of potential dependent memory accesses. typedef EquivalenceClasses DepCandidates; + /// Type to keep track of the status of the dependence check. The order of + /// the elements is important and has to be from most permissive to least + /// permissive. + enum class VectorizationSafetyStatus { + // Can vectorize safely without RT checks. All dependences are known to be + // safe. + Safe, + // Can possibly vectorize with RT checks to overcome unknown dependencies. + PossiblySafeWithRtChecks, + // Cannot vectorize due to known unsafe dependencies. + Unsafe, + }; + /// Dependece between memory access instructions. struct Dependence { /// The type of the dependence. @@ -146,7 +159,7 @@ public: Instruction *getDestination(const LoopAccessInfo &LAI) const; /// Dependence types that don't prevent vectorization. - static bool isSafeForVectorization(DepType Type); + static VectorizationSafetyStatus isSafeForVectorization(DepType Type); /// Lexically forward dependence. bool isForward() const; @@ -164,8 +177,8 @@ public: MemoryDepChecker(PredicatedScalarEvolution &PSE, const Loop *L) : PSE(PSE), InnermostLoop(L), AccessIdx(0), MaxSafeRegisterWidth(-1U), - ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true), - RecordDependences(true) {} + FoundNonConstantDistanceDependence(false), + Status(VectorizationSafetyStatus::Safe), RecordDependences(true) {} /// Register the location (instructions are given increasing numbers) /// of a write access. @@ -193,7 +206,9 @@ public: /// No memory dependence was encountered that would inhibit /// vectorization. - bool isSafeForVectorization() const { return SafeForVectorization; } + bool isSafeForVectorization() const { + return Status == VectorizationSafetyStatus::Safe; + } /// The maximum number of bytes of a vector register we can vectorize /// the accesses safely with. @@ -205,7 +220,10 @@ public: /// In same cases when the dependency check fails we can still /// vectorize the loop with a dynamic array access check. - bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; } + bool shouldRetryWithRuntimeCheck() const { + return FoundNonConstantDistanceDependence && + Status == VectorizationSafetyStatus::PossiblySafeWithRtChecks; + } /// Returns the memory dependences. If null is returned we exceeded /// the MaxDependences threshold and this information is not @@ -267,11 +285,12 @@ private: /// If we see a non-constant dependence distance we can still try to /// vectorize this loop with runtime checks. - bool ShouldRetryWithRuntimeCheck; + bool FoundNonConstantDistanceDependence; - /// No memory dependence was encountered that would inhibit - /// vectorization. - bool SafeForVectorization; + /// Result of the dependence checks, indicating whether the checked + /// dependences are safe for vectorization, require RT checks or are known to + /// be unsafe. + VectorizationSafetyStatus Status; //// True if Dependences reflects the dependences in the //// loop. If false we exceeded MaxDependences and @@ -304,6 +323,11 @@ private: /// \return false if we shouldn't vectorize at all or avoid larger /// vectorization factors by limiting MaxSafeDepDistBytes. bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize); + + /// Updates the current safety status with \p S. We can go from Safe to + /// either PossiblySafeWithRtChecks or Unsafe and from + /// PossiblySafeWithRtChecks to Unsafe. + void mergeInStatus(VectorizationSafetyStatus S); }; /// Holds information about the memory runtime legality checks to verify @@ -564,11 +588,10 @@ public: /// Print the information about the memory accesses in the loop. void print(raw_ostream &OS, unsigned Depth = 0) const; - /// Checks existence of store to invariant address inside loop. - /// If the loop has any store to invariant address, then it returns true, - /// else returns false. - bool hasStoreToLoopInvariantAddress() const { - return StoreToLoopInvariantAddress; + /// If the loop has memory dependence involving an invariant address, i.e. two + /// stores or a store and a load, then return true, else return false. + bool hasDependenceInvolvingLoopInvariantAddress() const { + return HasDependenceInvolvingLoopInvariantAddress; } /// Used to add runtime SCEV checks. Simplifies SCEV expressions and converts @@ -621,9 +644,8 @@ private: /// Cache the result of analyzeLoop. bool CanVecMem; - /// Indicator for storing to uniform addresses. - /// If a loop has write to a loop invariant address then it should be true. - bool StoreToLoopInvariantAddress; + /// Indicator that there are non vectorizable stores to a uniform address. + bool HasDependenceInvolvingLoopInvariantAddress; /// The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfo.h b/contrib/llvm/include/llvm/Analysis/LoopInfo.h index 30b29d66a1d..72873546a06 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfo.h @@ -408,6 +408,12 @@ public: /// Verify loop structure of this loop and all nested loops. void verifyLoopNest(DenseSet *Loops) const; + /// Returns true if the loop is annotated parallel. + /// + /// Derived classes can override this method using static template + /// polymorphism. + bool isAnnotatedParallel() const { return false; } + /// Print loop with all the BBs inside it. void print(raw_ostream &OS, unsigned Depth = 0, bool Verbose = false) const; @@ -989,6 +995,26 @@ public: /// Function to print a loop's contents as LLVM's text IR assembly. void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner = ""); +/// Find and return the loop attribute node for the attribute @p Name in +/// @p LoopID. Return nullptr if there is no such attribute. +MDNode *findOptionMDForLoopID(MDNode *LoopID, StringRef Name); + +/// Find string metadata for a loop. +/// +/// Returns the MDNode where the first operand is the metadata's name. The +/// following operands are the metadata's values. If no metadata with @p Name is +/// found, return nullptr. +MDNode *findOptionMDForLoop(const Loop *TheLoop, StringRef Name); + +/// Return whether an MDNode might represent an access group. +/// +/// Access group metadata nodes have to be distinct and empty. Being +/// always-empty ensures that it never needs to be changed (which -- because +/// MDNodes are designed immutable -- would require creating a new MDNode). Note +/// that this is not a sufficient condition: not every distinct and empty NDNode +/// is representing an access group. +bool isValidAsAccessGroup(MDNode *AccGroup); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h index 94138985886..2b807919fed 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -392,7 +392,10 @@ void LoopBase::verifyLoopNest( template void LoopBase::print(raw_ostream &OS, unsigned Depth, bool Verbose) const { - OS.indent(Depth * 2) << "Loop at depth " << getLoopDepth() << " containing: "; + OS.indent(Depth * 2); + if (static_cast(this)->isAnnotatedParallel()) + OS << "Parallel "; + OS << "Loop at depth " << getLoopDepth() << " containing: "; BlockT *H = getHeader(); for (unsigned i = 0; i < getBlocks().size(); ++i) { @@ -640,8 +643,8 @@ void LoopInfoBase::print(raw_ostream &OS) const { template bool compareVectors(std::vector &BB1, std::vector &BB2) { - llvm::sort(BB1.begin(), BB1.end()); - llvm::sort(BB2.begin(), BB2.end()); + llvm::sort(BB1); + llvm::sort(BB2); return BB1 == BB2; } diff --git a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h index 1c40cffc7f6..958d4fe4b83 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -37,7 +37,6 @@ namespace llvm { class AssumptionCache; -class CallSite; class DominatorTree; class Function; class Instruction; @@ -304,7 +303,7 @@ private: /// The maximum size of the dereferences of the pointer. /// /// May be UnknownSize if the sizes are unknown. - LocationSize Size = MemoryLocation::UnknownSize; + LocationSize Size = LocationSize::unknown(); /// The AA tags associated with dereferences of the pointer. /// /// The members may be null if there are no tags or conflicting tags. @@ -398,7 +397,7 @@ public: /// invalidated on the next non-local query or when an instruction is /// removed. Clients must copy this data if they want it around longer than /// that. - const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS); + const NonLocalDepInfo &getNonLocalCallDependency(CallBase *QueryCall); /// Perform a full dependency query for an access to the QueryInst's /// specified memory location, returning the set of instructions that either @@ -482,9 +481,9 @@ public: void releaseMemory(); private: - MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, - BasicBlock::iterator ScanIt, - BasicBlock *BB); + MemDepResult getCallDependencyFrom(CallBase *Call, bool isReadOnlyCall, + BasicBlock::iterator ScanIt, + BasicBlock *BB); bool getNonLocalPointerDepFromBB(Instruction *QueryInst, const PHITransAddr &Pointer, const MemoryLocation &Loc, bool isLoad, diff --git a/contrib/llvm/include/llvm/Analysis/MemoryLocation.h b/contrib/llvm/include/llvm/Analysis/MemoryLocation.h index 6b680000312..fca18c1b599 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryLocation.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryLocation.h @@ -16,9 +16,9 @@ #ifndef LLVM_ANALYSIS_MEMORYLOCATION_H #define LLVM_ANALYSIS_MEMORYLOCATION_H -#include "llvm/ADT/Optional.h" #include "llvm/ADT/DenseMapInfo.h" -#include "llvm/IR/CallSite.h" +#include "llvm/ADT/Optional.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Metadata.h" namespace llvm { @@ -34,8 +34,134 @@ class AnyMemIntrinsic; class TargetLibraryInfo; // Represents the size of a MemoryLocation. Logically, it's an -// Optional, with a special UnknownSize value from `MemoryLocation`. -using LocationSize = uint64_t; +// Optional that also carries a bit to represent whether the integer +// it contains, N, is 'precise'. Precise, in this context, means that we know +// that the area of storage referenced by the given MemoryLocation must be +// precisely N bytes. An imprecise value is formed as the union of two or more +// precise values, and can conservatively represent all of the values unioned +// into it. Importantly, imprecise values are an *upper-bound* on the size of a +// MemoryLocation. +// +// Concretely, a precise MemoryLocation is (%p, 4) in +// store i32 0, i32* %p +// +// Since we know that %p must be at least 4 bytes large at this point. +// Otherwise, we have UB. An example of an imprecise MemoryLocation is (%p, 4) +// at the memcpy in +// +// %n = select i1 %foo, i64 1, i64 4 +// call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %baz, i64 %n, i32 1, +// i1 false) +// +// ...Since we'll copy *up to* 4 bytes into %p, but we can't guarantee that +// we'll ever actually do so. +// +// If asked to represent a pathologically large value, this will degrade to +// None. +class LocationSize { + enum : uint64_t { + Unknown = ~uint64_t(0), + ImpreciseBit = uint64_t(1) << 63, + MapEmpty = Unknown - 1, + MapTombstone = Unknown - 2, + + // The maximum value we can represent without falling back to 'unknown'. + MaxValue = (MapTombstone - 1) & ~ImpreciseBit, + }; + + uint64_t Value; + + // Hack to support implicit construction. This should disappear when the + // public LocationSize ctor goes away. + enum DirectConstruction { Direct }; + + constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {} + + static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition."); +public: + // FIXME: Migrate all users to construct via either `precise` or `upperBound`, + // to make it more obvious at the callsite the kind of size that they're + // providing. + // + // Since the overwhelming majority of users of this provide precise values, + // this assumes the provided value is precise. + constexpr LocationSize(uint64_t Raw) + : Value(Raw > MaxValue ? Unknown : Raw) {} + + static LocationSize precise(uint64_t Value) { return LocationSize(Value); } + + static LocationSize upperBound(uint64_t Value) { + // You can't go lower than 0, so give a precise result. + if (LLVM_UNLIKELY(Value == 0)) + return precise(0); + if (LLVM_UNLIKELY(Value > MaxValue)) + return unknown(); + return LocationSize(Value | ImpreciseBit, Direct); + } + + constexpr static LocationSize unknown() { + return LocationSize(Unknown, Direct); + } + + // Sentinel values, generally used for maps. + constexpr static LocationSize mapTombstone() { + return LocationSize(MapTombstone, Direct); + } + constexpr static LocationSize mapEmpty() { + return LocationSize(MapEmpty, Direct); + } + + // Returns a LocationSize that can correctly represent either `*this` or + // `Other`. + LocationSize unionWith(LocationSize Other) const { + if (Other == *this) + return *this; + + if (!hasValue() || !Other.hasValue()) + return unknown(); + + return upperBound(std::max(getValue(), Other.getValue())); + } + + bool hasValue() const { return Value != Unknown; } + uint64_t getValue() const { + assert(hasValue() && "Getting value from an unknown LocationSize!"); + return Value & ~ImpreciseBit; + } + + // Returns whether or not this value is precise. Note that if a value is + // precise, it's guaranteed to not be `unknown()`. + bool isPrecise() const { + return (Value & ImpreciseBit) == 0; + } + + // Convenience method to check if this LocationSize's value is 0. + bool isZero() const { return hasValue() && getValue() == 0; } + + bool operator==(const LocationSize &Other) const { + return Value == Other.Value; + } + + bool operator!=(const LocationSize &Other) const { + return !(*this == Other); + } + + // Ordering operators are not provided, since it's unclear if there's only one + // reasonable way to compare: + // - values that don't exist against values that do, and + // - precise values to imprecise values + + void print(raw_ostream &OS) const; + + // Returns an opaque value that represents this LocationSize. Cannot be + // reliably converted back into a LocationSize. + uint64_t toRaw() const { return Value; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, LocationSize Size) { + Size.print(OS); + return OS; +} /// Representation for a specific memory location. /// @@ -108,11 +234,15 @@ public: static MemoryLocation getForDest(const AnyMemIntrinsic *MI); /// Return a location representing a particular argument of a call. - static MemoryLocation getForArgument(ImmutableCallSite CS, unsigned ArgIdx, - const TargetLibraryInfo &TLI); + static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, + const TargetLibraryInfo *TLI); + static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, + const TargetLibraryInfo &TLI) { + return getForArgument(Call, ArgIdx, &TLI); + } explicit MemoryLocation(const Value *Ptr = nullptr, - LocationSize Size = UnknownSize, + LocationSize Size = LocationSize::unknown(), const AAMDNodes &AATags = AAMDNodes()) : Ptr(Ptr), Size(Size), AATags(AATags) {} @@ -139,13 +269,30 @@ public: } }; -// Specialize DenseMapInfo for MemoryLocation. +// Specialize DenseMapInfo. +template <> struct DenseMapInfo { + static inline LocationSize getEmptyKey() { + return LocationSize::mapEmpty(); + } + static inline LocationSize getTombstoneKey() { + return LocationSize::mapTombstone(); + } + static unsigned getHashValue(const LocationSize &Val) { + return DenseMapInfo::getHashValue(Val.toRaw()); + } + static bool isEqual(const LocationSize &LHS, const LocationSize &RHS) { + return LHS == RHS; + } +}; + template <> struct DenseMapInfo { static inline MemoryLocation getEmptyKey() { - return MemoryLocation(DenseMapInfo::getEmptyKey(), 0); + return MemoryLocation(DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey()); } static inline MemoryLocation getTombstoneKey() { - return MemoryLocation(DenseMapInfo::getTombstoneKey(), 0); + return MemoryLocation(DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey()); } static unsigned getHashValue(const MemoryLocation &Val) { return DenseMapInfo::getHashValue(Val.Ptr) ^ diff --git a/contrib/llvm/include/llvm/Analysis/MemorySSA.h b/contrib/llvm/include/llvm/Analysis/MemorySSA.h index d445e4430e5..17e2d0c7397 100644 --- a/contrib/llvm/include/llvm/Analysis/MemorySSA.h +++ b/contrib/llvm/include/llvm/Analysis/MemorySSA.h @@ -280,9 +280,10 @@ protected: friend class MemorySSAUpdater; MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty, - DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB) - : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInstruction(MI), - OptimizedAccessAlias(MayAlias) { + DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB, + unsigned NumOperands) + : MemoryAccess(C, Vty, DeleteValue, BB, NumOperands), + MemoryInstruction(MI), OptimizedAccessAlias(MayAlias) { setDefiningAccess(DMA); } @@ -308,11 +309,6 @@ private: Optional OptimizedAccessAlias; }; -template <> -struct OperandTraits - : public FixedNumOperandTraits {}; -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess) - /// Represents read-only accesses to memory /// /// In particular, the set of Instructions that will be represented by @@ -323,7 +319,8 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB) - : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB) {} + : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB, + /*NumOperands=*/1) {} // allocate space for exactly one operand void *operator new(size_t s) { return User::operator new(s, 1); } @@ -381,31 +378,33 @@ public: MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB, unsigned Ver) - : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB), ID(Ver) {} + : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB, + /*NumOperands=*/2), + ID(Ver) {} - // allocate space for exactly one operand - void *operator new(size_t s) { return User::operator new(s, 1); } + // allocate space for exactly two operands + void *operator new(size_t s) { return User::operator new(s, 2); } static bool classof(const Value *MA) { return MA->getValueID() == MemoryDefVal; } void setOptimized(MemoryAccess *MA) { - Optimized = MA; - OptimizedID = getDefiningAccess()->getID(); + setOperand(1, MA); + OptimizedID = MA->getID(); } MemoryAccess *getOptimized() const { - return cast_or_null(Optimized); + return cast_or_null(getOperand(1)); } bool isOptimized() const { - return getOptimized() && getDefiningAccess() && - OptimizedID == getDefiningAccess()->getID(); + return getOptimized() && OptimizedID == getOptimized()->getID(); } void resetOptimized() { OptimizedID = INVALID_MEMORYACCESS_ID; + setOperand(1, nullptr); } void print(raw_ostream &OS) const; @@ -417,13 +416,34 @@ private: const unsigned ID; unsigned OptimizedID = INVALID_MEMORYACCESS_ID; - WeakVH Optimized; }; template <> -struct OperandTraits : public FixedNumOperandTraits {}; +struct OperandTraits : public FixedNumOperandTraits {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess) +template <> +struct OperandTraits { + static Use *op_begin(MemoryUseOrDef *MUD) { + if (auto *MU = dyn_cast(MUD)) + return OperandTraits::op_begin(MU); + return OperandTraits::op_begin(cast(MUD)); + } + + static Use *op_end(MemoryUseOrDef *MUD) { + if (auto *MU = dyn_cast(MUD)) + return OperandTraits::op_end(MU); + return OperandTraits::op_end(cast(MUD)); + } + + static unsigned operands(const MemoryUseOrDef *MUD) { + if (const auto *MU = dyn_cast(MUD)) + return OperandTraits::operands(MU); + return OperandTraits::operands(cast(MUD)); + } +}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess) + /// Represents phi nodes for memory accesses. /// /// These have the same semantic as regular phi nodes, with the exception that @@ -684,13 +704,19 @@ public: ~MemorySSA(); MemorySSAWalker *getWalker(); + MemorySSAWalker *getSkipSelfWalker(); /// Given a memory Mod/Ref'ing instruction, get the MemorySSA /// access associated with it. If passed a basic block gets the memory phi /// node that exists for that block, if there is one. Otherwise, this will get /// a MemoryUseOrDef. - MemoryUseOrDef *getMemoryAccess(const Instruction *) const; - MemoryPhi *getMemoryAccess(const BasicBlock *BB) const; + MemoryUseOrDef *getMemoryAccess(const Instruction *I) const { + return cast_or_null(ValueToMemoryAccess.lookup(I)); + } + + MemoryPhi *getMemoryAccess(const BasicBlock *BB) const { + return cast_or_null(ValueToMemoryAccess.lookup(cast(BB))); + } void dump() const; void print(raw_ostream &) const; @@ -750,6 +776,9 @@ public: /// all uses, uses appear in the right places). This is used by unit tests. void verifyMemorySSA() const; + /// Check clobber sanity for an access. + void checkClobberSanityAccess(const MemoryAccess *MA) const; + /// Used in various insertion functions to specify whether we are talking /// about the beginning or end of a block. enum InsertionPlace { Beginning, End }; @@ -764,6 +793,7 @@ protected: void verifyDomination(Function &F) const; void verifyOrdering(Function &F) const; void verifyDominationNumbers(const Function &F) const; + void verifyClobberSanity(const Function &F) const; // This is used by the use optimizer and updater. AccessList *getWritableBlockAccesses(const BasicBlock *BB) const { @@ -796,16 +826,20 @@ protected: InsertionPlace); void insertIntoListsBefore(MemoryAccess *, const BasicBlock *, AccessList::iterator); - MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *); + MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *, + const MemoryUseOrDef *Template = nullptr); private: + class ClobberWalkerBase; class CachingWalker; + class SkipSelfWalker; class OptimizeUses; CachingWalker *getWalkerImpl(); void buildMemorySSA(); void optimizeUses(); + void prepareForMoveTo(MemoryAccess *, BasicBlock *); void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const; using AccessMap = DenseMap>; @@ -816,7 +850,8 @@ private: void markUnreachableAsLiveOnEntry(BasicBlock *BB); bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const; MemoryPhi *createMemoryPhi(BasicBlock *BB); - MemoryUseOrDef *createNewAccess(Instruction *); + MemoryUseOrDef *createNewAccess(Instruction *, + const MemoryUseOrDef *Template = nullptr); MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace); void placePHINodes(const SmallPtrSetImpl &); MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool); @@ -851,7 +886,9 @@ private: mutable DenseMap BlockNumbering; // Memory SSA building info + std::unique_ptr WalkerBase; std::unique_ptr Walker; + std::unique_ptr SkipWalker; unsigned NextID; }; diff --git a/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h index 38f08c1eebd..169d5bd9fa8 100644 --- a/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h +++ b/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h @@ -35,8 +35,11 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopIterator.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFGDiff.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Module.h" #include "llvm/IR/OperandTraits.h" @@ -45,6 +48,7 @@ #include "llvm/IR/User.h" #include "llvm/IR/Value.h" #include "llvm/IR/ValueHandle.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -57,6 +61,12 @@ class MemoryAccess; class LLVMContext; class raw_ostream; +using ValueToValueMapTy = ValueMap; +using PhiToDefMap = SmallDenseMap; +using CFGUpdate = cfg::Update; +using GraphDiffInvBBPair = + std::pair *, Inverse>; + class MemorySSAUpdater { private: MemorySSA *MSSA; @@ -70,6 +80,7 @@ private: public: MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {} + /// Insert a definition into the MemorySSA IR. RenameUses will rename any use /// below the new def block (and any inserted phis). RenameUses should be set /// to true if the definition may cause new aliases for loads below it. This @@ -89,15 +100,48 @@ public: /// Where a mayalias b, *does* require RenameUses be set to true. void insertDef(MemoryDef *Def, bool RenameUses = false); void insertUse(MemoryUse *Use); + /// Update the MemoryPhi in `To` following an edge deletion between `From` and + /// `To`. If `To` becomes unreachable, a call to removeBlocks should be made. + void removeEdge(BasicBlock *From, BasicBlock *To); + /// Update the MemoryPhi in `To` to have a single incoming edge from `From`, + /// following a CFG change that replaced multiple edges (switch) with a direct + /// branch. + void removeDuplicatePhiEdgesBetween(BasicBlock *From, BasicBlock *To); + /// Update MemorySSA after a loop was cloned, given the blocks in RPO order, + /// the exit blocks and a 1:1 mapping of all blocks and instructions + /// cloned. This involves duplicating all defs and uses in the cloned blocks + /// Updating phi nodes in exit block successors is done separately. + void updateForClonedLoop(const LoopBlocksRPO &LoopBlocks, + ArrayRef ExitBlocks, + const ValueToValueMapTy &VM, + bool IgnoreIncomingWithNoClones = false); + // Block BB was fully or partially cloned into its predecessor P1. Map + // contains the 1:1 mapping of instructions cloned and VM[BB]=P1. + void updateForClonedBlockIntoPred(BasicBlock *BB, BasicBlock *P1, + const ValueToValueMapTy &VM); + /// Update phi nodes in exit block successors following cloning. Exit blocks + /// that were not cloned don't have additional predecessors added. + void updateExitBlocksForClonedLoop(ArrayRef ExitBlocks, + const ValueToValueMapTy &VMap, + DominatorTree &DT); + void updateExitBlocksForClonedLoop( + ArrayRef ExitBlocks, + ArrayRef> VMaps, DominatorTree &DT); + + /// Apply CFG updates, analogous with the DT edge updates. + void applyUpdates(ArrayRef Updates, DominatorTree &DT); + /// Apply CFG insert updates, analogous with the DT edge updates. + void applyInsertUpdates(ArrayRef Updates, DominatorTree &DT); + void moveBefore(MemoryUseOrDef *What, MemoryUseOrDef *Where); void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where); void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB, MemorySSA::InsertionPlace Where); - /// `From` block was spliced into `From` and `To`. - /// Move all accesses from `From` to `To` starting at instruction `Start`. - /// `To` is newly created BB, so empty of MemorySSA::MemoryAccesses. - /// Edges are already updated, so successors of `To` with MPhi nodes need to - /// update incoming block. + /// `From` block was spliced into `From` and `To`. There is a CFG edge from + /// `From` to `To`. Move all accesses from `From` to `To` starting at + /// instruction `Start`. `To` is newly created BB, so empty of + /// MemorySSA::MemoryAccesses. Edges are already updated, so successors of + /// `To` with MPhi nodes need to update incoming block. /// |------| |------| /// | From | | From | /// | | |------| @@ -108,12 +152,12 @@ public: /// |------| |------| void moveAllAfterSpliceBlocks(BasicBlock *From, BasicBlock *To, Instruction *Start); - /// `From` block was merged into `To`. All instructions were moved and - /// `From` is an empty block with successor edges; `From` is about to be - /// deleted. Move all accesses from `From` to `To` starting at instruction - /// `Start`. `To` may have multiple successors, `From` has a single - /// predecessor. `From` may have successors with MPhi nodes, replace their - /// incoming block with `To`. + /// `From` block was merged into `To`. There is a CFG edge from `To` to + /// `From`.`To` still branches to `From`, but all instructions were moved and + /// `From` is now an empty block; `From` is about to be deleted. Move all + /// accesses from `From` to `To` starting at instruction `Start`. `To` may + /// have multiple successors, `From` has a single predecessor. `From` may have + /// successors with MPhi nodes, replace their incoming block with `To`. /// |------| |------| /// | To | | To | /// |------| | | @@ -124,15 +168,14 @@ public: /// |------| |------| void moveAllAfterMergeBlocks(BasicBlock *From, BasicBlock *To, Instruction *Start); - /// BasicBlock Old had New, an empty BasicBlock, added directly before it, - /// and the predecessors in Preds that used to point to Old, now point to - /// New. If New is the only predecessor, move Old's Phi, if present, to New. + /// A new empty BasicBlock (New) now branches directly to Old. Some of + /// Old's predecessors (Preds) are now branching to New instead of Old. + /// If New is the only predecessor, move Old's Phi, if present, to New. /// Otherwise, add a new Phi in New with appropriate incoming values, and /// update the incoming values in Old's Phi node too, if present. - void - wireOldPredecessorsToNewImmediatePredecessor(BasicBlock *Old, BasicBlock *New, - ArrayRef Preds); - + void wireOldPredecessorsToNewImmediatePredecessor( + BasicBlock *Old, BasicBlock *New, ArrayRef Preds, + bool IdenticalEdgesWereMerged = true); // The below are utility functions. Other than creation of accesses to pass // to insertDef, and removeAccess to remove accesses, you should generally // not attempt to update memoryssa yourself. It is very non-trivial to get @@ -220,6 +263,23 @@ private: template MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands); void fixupDefs(const SmallVectorImpl &); + // Clone all uses and defs from BB to NewBB given a 1:1 map of all + // instructions and blocks cloned, and a map of MemoryPhi : Definition + // (MemoryAccess Phi or Def). VMap maps old instructions to cloned + // instructions and old blocks to cloned blocks. MPhiMap, is created in the + // caller of this private method, and maps existing MemoryPhis to new + // definitions that new MemoryAccesses must point to. These definitions may + // not necessarily be MemoryPhis themselves, they may be MemoryDefs. As such, + // the map is between MemoryPhis and MemoryAccesses, where the MemoryAccesses + // may be MemoryPhis or MemoryDefs and not MemoryUses. + void cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB, + const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap); + template + void privateUpdateExitBlocksForClonedLoop(ArrayRef ExitBlocks, + Iter ValuesBegin, Iter ValuesEnd, + DominatorTree &DT); + void applyInsertUpdates(ArrayRef, DominatorTree &DT, + const GraphDiff *GD); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Analysis/MustExecute.h b/contrib/llvm/include/llvm/Analysis/MustExecute.h index 97ad76d451c..ad3222c17e6 100644 --- a/contrib/llvm/include/llvm/Analysis/MustExecute.h +++ b/contrib/llvm/include/llvm/Analysis/MustExecute.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/InstructionPrecedenceTracking.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Dominators.h" @@ -31,33 +32,138 @@ class DominatorTree; class Loop; /// Captures loop safety information. -/// It keep information for loop & its header may throw exception or otherwise +/// It keep information for loop blocks may throw exception or otherwise /// exit abnormaly on any iteration of the loop which might actually execute /// at runtime. The primary way to consume this infromation is via /// isGuaranteedToExecute below, but some callers bailout or fallback to /// alternate reasoning if a loop contains any implicit control flow. -struct LoopSafetyInfo { - bool MayThrow = false; // The current loop contains an instruction which - // may throw. - bool HeaderMayThrow = false; // Same as previous, but specific to loop header +/// NOTE: LoopSafetyInfo contains cached information regarding loops and their +/// particular blocks. This information is only dropped on invocation of +/// computeLoopSafetyInfo. If the loop or any of its block is deleted, or if +/// any thrower instructions have been added or removed from them, or if the +/// control flow has changed, or in case of other meaningful modifications, the +/// LoopSafetyInfo needs to be recomputed. If a meaningful modifications to the +/// loop were made and the info wasn't recomputed properly, the behavior of all +/// methods except for computeLoopSafetyInfo is undefined. +class LoopSafetyInfo { // Used to update funclet bundle operands. DenseMap BlockColors; +protected: + /// Computes block colors. + void computeBlockColors(const Loop *CurLoop); + +public: + /// Returns block colors map that is used to update funclet operand bundles. + const DenseMap &getBlockColors() const; + + /// Copy colors of block \p Old into the block \p New. + void copyColors(BasicBlock *New, BasicBlock *Old); + + /// Returns true iff the block \p BB potentially may throw exception. It can + /// be false-positive in cases when we want to avoid complex analysis. + virtual bool blockMayThrow(const BasicBlock *BB) const = 0; + + /// Returns true iff any block of the loop for which this info is contains an + /// instruction that may throw or otherwise exit abnormally. + virtual bool anyBlockMayThrow() const = 0; + + /// Return true if we must reach the block \p BB under assumption that the + /// loop \p CurLoop is entered. + bool allLoopPathsLeadToBlock(const Loop *CurLoop, const BasicBlock *BB, + const DominatorTree *DT) const; + + /// Computes safety information for a loop checks loop body & header for + /// the possibility of may throw exception, it takes LoopSafetyInfo and loop + /// as argument. Updates safety information in LoopSafetyInfo argument. + /// Note: This is defined to clear and reinitialize an already initialized + /// LoopSafetyInfo. Some callers rely on this fact. + virtual void computeLoopSafetyInfo(const Loop *CurLoop) = 0; + + /// Returns true if the instruction in a loop is guaranteed to execute at + /// least once (under the assumption that the loop is entered). + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const = 0; + LoopSafetyInfo() = default; + + virtual ~LoopSafetyInfo() = default; }; -/// Computes safety information for a loop checks loop body & header for -/// the possibility of may throw exception, it takes LoopSafetyInfo and loop as -/// argument. Updates safety information in LoopSafetyInfo argument. -/// Note: This is defined to clear and reinitialize an already initialized -/// LoopSafetyInfo. Some callers rely on this fact. -void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *); -/// Returns true if the instruction in a loop is guaranteed to execute at least -/// once (under the assumption that the loop is entered). -bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, - const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo); +/// Simple and conservative implementation of LoopSafetyInfo that can give +/// false-positive answers to its queries in order to avoid complicated +/// analysis. +class SimpleLoopSafetyInfo: public LoopSafetyInfo { + bool MayThrow = false; // The current loop contains an instruction which + // may throw. + bool HeaderMayThrow = false; // Same as previous, but specific to loop header + +public: + virtual bool blockMayThrow(const BasicBlock *BB) const; + + virtual bool anyBlockMayThrow() const; + + virtual void computeLoopSafetyInfo(const Loop *CurLoop); + + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const; + + SimpleLoopSafetyInfo() : LoopSafetyInfo() {}; + + virtual ~SimpleLoopSafetyInfo() {}; +}; + +/// This implementation of LoopSafetyInfo use ImplicitControlFlowTracking to +/// give precise answers on "may throw" queries. This implementation uses cache +/// that should be invalidated by calling the methods insertInstructionTo and +/// removeInstruction whenever we modify a basic block's contents by adding or +/// removing instructions. +class ICFLoopSafetyInfo: public LoopSafetyInfo { + bool MayThrow = false; // The current loop contains an instruction which + // may throw. + // Contains information about implicit control flow in this loop's blocks. + mutable ImplicitControlFlowTracking ICF; + // Contains information about instruction that may possibly write memory. + mutable MemoryWriteTracking MW; + +public: + virtual bool blockMayThrow(const BasicBlock *BB) const; + + virtual bool anyBlockMayThrow() const; + + virtual void computeLoopSafetyInfo(const Loop *CurLoop); + + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const; + + /// Returns true if we could not execute a memory-modifying instruction before + /// we enter \p BB under assumption that \p CurLoop is entered. + bool doesNotWriteMemoryBefore(const BasicBlock *BB, const Loop *CurLoop) + const; + + /// Returns true if we could not execute a memory-modifying instruction before + /// we execute \p I under assumption that \p CurLoop is entered. + bool doesNotWriteMemoryBefore(const Instruction &I, const Loop *CurLoop) + const; + + /// Inform the safety info that we are planning to insert a new instruction + /// \p Inst into the basic block \p BB. It will make all cache updates to keep + /// it correct after this insertion. + void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB); + + /// Inform safety info that we are planning to remove the instruction \p Inst + /// from its block. It will make all cache updates to keep it correct after + /// this removal. + void removeInstruction(const Instruction *Inst); + + ICFLoopSafetyInfo(DominatorTree *DT) : LoopSafetyInfo(), ICF(DT), MW(DT) {}; + + virtual ~ICFLoopSafetyInfo() {}; +}; } diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h index 559c77c3081..58a67042ea2 100644 --- a/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h @@ -60,7 +60,7 @@ public: FunctionModRefBehavior getModRefBehavior(const Function *F); using AAResultBase::getModRefInfo; - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); }; /// Analysis pass providing a never-invalidated alias analysis result. diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h index 07beb0bb60a..1f497fab35d 100644 --- a/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ b/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -51,25 +51,25 @@ extern bool EnableARCOpts; /// on. inline bool ModuleHasARC(const Module &M) { return - M.getNamedValue("objc_retain") || - M.getNamedValue("objc_release") || - M.getNamedValue("objc_autorelease") || - M.getNamedValue("objc_retainAutoreleasedReturnValue") || - M.getNamedValue("objc_unsafeClaimAutoreleasedReturnValue") || - M.getNamedValue("objc_retainBlock") || - M.getNamedValue("objc_autoreleaseReturnValue") || - M.getNamedValue("objc_autoreleasePoolPush") || - M.getNamedValue("objc_loadWeakRetained") || - M.getNamedValue("objc_loadWeak") || - M.getNamedValue("objc_destroyWeak") || - M.getNamedValue("objc_storeWeak") || - M.getNamedValue("objc_initWeak") || - M.getNamedValue("objc_moveWeak") || - M.getNamedValue("objc_copyWeak") || - M.getNamedValue("objc_retainedObject") || - M.getNamedValue("objc_unretainedObject") || - M.getNamedValue("objc_unretainedPointer") || - M.getNamedValue("clang.arc.use"); + M.getNamedValue("llvm.objc.retain") || + M.getNamedValue("llvm.objc.release") || + M.getNamedValue("llvm.objc.autorelease") || + M.getNamedValue("llvm.objc.retainAutoreleasedReturnValue") || + M.getNamedValue("llvm.objc.unsafeClaimAutoreleasedReturnValue") || + M.getNamedValue("llvm.objc.retainBlock") || + M.getNamedValue("llvm.objc.autoreleaseReturnValue") || + M.getNamedValue("llvm.objc.autoreleasePoolPush") || + M.getNamedValue("llvm.objc.loadWeakRetained") || + M.getNamedValue("llvm.objc.loadWeak") || + M.getNamedValue("llvm.objc.destroyWeak") || + M.getNamedValue("llvm.objc.storeWeak") || + M.getNamedValue("llvm.objc.initWeak") || + M.getNamedValue("llvm.objc.moveWeak") || + M.getNamedValue("llvm.objc.copyWeak") || + M.getNamedValue("llvm.objc.retainedObject") || + M.getNamedValue("llvm.objc.unretainedObject") || + M.getNamedValue("llvm.objc.unretainedPointer") || + M.getNamedValue("llvm.objc.clang.arc.use"); } /// This is a wrapper around getUnderlyingObject which also knows how to diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h b/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h index 0b92d8b4835..018ea1f851b 100644 --- a/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h +++ b/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h @@ -11,6 +11,7 @@ #define LLVM_ANALYSIS_OBJCARCINSTKIND_H #include "llvm/IR/Function.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Instructions.h" namespace llvm { @@ -48,7 +49,7 @@ enum class ARCInstKind { CopyWeak, ///< objc_copyWeak (derived) DestroyWeak, ///< objc_destroyWeak (derived) StoreStrong, ///< objc_storeStrong (derived) - IntrinsicUser, ///< clang.arc.use + IntrinsicUser, ///< llvm.objc.clang.arc.use CallOrUser, ///< could call objc_release and/or "use" pointers Call, ///< could call objc_release User, ///< could "use" a pointer diff --git a/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h b/contrib/llvm/include/llvm/Analysis/OrderedInstructions.h similarity index 93% rename from contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h rename to contrib/llvm/include/llvm/Analysis/OrderedInstructions.h index 7f57fde638b..7e3850b87c5 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h +++ b/contrib/llvm/include/llvm/Analysis/OrderedInstructions.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H -#define LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H +#ifndef LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H +#define LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H #include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/OrderedBasicBlock.h" @@ -62,4 +62,4 @@ public: } // end namespace llvm -#endif // LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H +#endif // LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H diff --git a/contrib/llvm/include/llvm/Analysis/Passes.h b/contrib/llvm/include/llvm/Analysis/Passes.h index 09b28a0b088..081dd500083 100644 --- a/contrib/llvm/include/llvm/Analysis/Passes.h +++ b/contrib/llvm/include/llvm/Analysis/Passes.h @@ -61,10 +61,10 @@ namespace llvm { //===--------------------------------------------------------------------===// // - // createDivergenceAnalysisPass - This pass determines which branches in a GPU + // createLegacyDivergenceAnalysisPass - This pass determines which branches in a GPU // program are divergent. // - FunctionPass *createDivergenceAnalysisPass(); + FunctionPass *createLegacyDivergenceAnalysisPass(); //===--------------------------------------------------------------------===// // diff --git a/contrib/llvm/include/llvm/Analysis/PhiValues.h b/contrib/llvm/include/llvm/Analysis/PhiValues.h index 6607b329c04..76204ac1bc6 100644 --- a/contrib/llvm/include/llvm/Analysis/PhiValues.h +++ b/contrib/llvm/include/llvm/Analysis/PhiValues.h @@ -88,6 +88,22 @@ private: /// All values reachable from each component. DenseMap ReachableMap; + /// A CallbackVH to notify PhiValues when a value is deleted or replaced, so + /// that the cached information for that value can be cleared to avoid + /// dangling pointers to invalid values. + class PhiValuesCallbackVH final : public CallbackVH { + PhiValues *PV; + void deleted() override; + void allUsesReplacedWith(Value *New) override; + + public: + PhiValuesCallbackVH(Value *V, PhiValues *PV = nullptr) + : CallbackVH(V), PV(PV) {} + }; + + /// A set of callbacks to the values that processPhi has seen. + DenseSet> TrackedValues; + /// The function that the PhiValues is for. const Function &F; diff --git a/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h b/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h index 58b67e74ba5..3aef4be72d7 100644 --- a/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h +++ b/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h @@ -98,14 +98,14 @@ public: bool isFunctionEntryCold(const Function *F); /// Returns true if \p F contains only cold code. bool isFunctionColdInCallGraph(const Function *F, BlockFrequencyInfo &BFI); - /// Returns true if \p F is a hot function. + /// Returns true if count \p C is considered hot. bool isHotCount(uint64_t C); /// Returns true if count \p C is considered cold. bool isColdCount(uint64_t C); - /// Returns true if BasicBlock \p B is considered hot. - bool isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI); - /// Returns true if BasicBlock \p B is considered cold. - bool isColdBB(const BasicBlock *B, BlockFrequencyInfo *BFI); + /// Returns true if BasicBlock \p BB is considered hot. + bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI); + /// Returns true if BasicBlock \p BB is considered cold. + bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI); /// Returns true if CallSite \p CS is considered hot. bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI); /// Returns true if Callsite \p CS is considered cold. @@ -134,9 +134,8 @@ public: static char ID; ProfileSummaryInfoWrapperPass(); - ProfileSummaryInfo *getPSI() { - return &*PSI; - } + ProfileSummaryInfo &getPSI() { return *PSI; } + const ProfileSummaryInfo &getPSI() const { return *PSI; } bool doInitialization(Module &M) override; bool doFinalization(Module &M) override; diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index 89918e3c205..8f4200b07e5 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -1833,6 +1833,10 @@ private: const SCEV *getOrCreateMulExpr(SmallVectorImpl &Ops, SCEV::NoWrapFlags Flags); + // Get addrec expr already created or create a new one. + const SCEV *getOrCreateAddRecExpr(SmallVectorImpl &Ops, + const Loop *L, SCEV::NoWrapFlags Flags); + /// Return x if \p Val is f(x) where f is a 1-1 function. const SCEV *stripInjectiveFunctions(const SCEV *Val) const; diff --git a/contrib/llvm/include/llvm/Analysis/ScopedNoAliasAA.h b/contrib/llvm/include/llvm/Analysis/ScopedNoAliasAA.h index 508968e16e5..1356c6e9198 100644 --- a/contrib/llvm/include/llvm/Analysis/ScopedNoAliasAA.h +++ b/contrib/llvm/include/llvm/Analysis/ScopedNoAliasAA.h @@ -16,7 +16,7 @@ #define LLVM_ANALYSIS_SCOPEDNOALIASAA_H #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/IR/CallSite.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include @@ -41,8 +41,8 @@ public: } AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc); - ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); private: bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const; diff --git a/contrib/llvm/include/llvm/Analysis/SparsePropagation.h b/contrib/llvm/include/llvm/Analysis/SparsePropagation.h index defcf96afb2..02a2e64268b 100644 --- a/contrib/llvm/include/llvm/Analysis/SparsePropagation.h +++ b/contrib/llvm/include/llvm/Analysis/SparsePropagation.h @@ -189,12 +189,12 @@ private: /// getFeasibleSuccessors - Return a vector of booleans to indicate which /// successors are reachable from a given terminator instruction. - void getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl &Succs, + void getFeasibleSuccessors(Instruction &TI, SmallVectorImpl &Succs, bool AggressiveUndef); void visitInst(Instruction &I); void visitPHINode(PHINode &I); - void visitTerminatorInst(TerminatorInst &TI); + void visitTerminator(Instruction &TI); }; //===----------------------------------------------------------------------===// @@ -286,7 +286,7 @@ void SparseSolver::markEdgeExecutable( template void SparseSolver::getFeasibleSuccessors( - TerminatorInst &TI, SmallVectorImpl &Succs, bool AggressiveUndef) { + Instruction &TI, SmallVectorImpl &Succs, bool AggressiveUndef) { Succs.resize(TI.getNumSuccessors()); if (TI.getNumSuccessors() == 0) return; @@ -330,7 +330,7 @@ void SparseSolver::getFeasibleSuccessors( return; } - if (TI.isExceptional()) { + if (TI.isExceptionalTerminator()) { Succs.assign(Succs.size(), true); return; } @@ -374,7 +374,7 @@ template bool SparseSolver::isEdgeFeasible( BasicBlock *From, BasicBlock *To, bool AggressiveUndef) { SmallVector SuccFeasible; - TerminatorInst *TI = From->getTerminator(); + Instruction *TI = From->getTerminator(); getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef); for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) @@ -385,8 +385,8 @@ bool SparseSolver::isEdgeFeasible( } template -void SparseSolver::visitTerminatorInst( - TerminatorInst &TI) { +void SparseSolver::visitTerminator( + Instruction &TI) { SmallVector SuccFeasible; getFeasibleSuccessors(TI, SuccFeasible, true); @@ -465,8 +465,8 @@ void SparseSolver::visitInst(Instruction &I) { if (ChangedValue.second != LatticeFunc->getUntrackedVal()) UpdateState(ChangedValue.first, ChangedValue.second); - if (TerminatorInst *TI = dyn_cast(&I)) - visitTerminatorInst(*TI); + if (I.isTerminator()) + visitTerminator(I); } template diff --git a/contrib/llvm/include/llvm/Analysis/StackSafetyAnalysis.h b/contrib/llvm/include/llvm/Analysis/StackSafetyAnalysis.h new file mode 100644 index 00000000000..8a151650a34 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/StackSafetyAnalysis.h @@ -0,0 +1,120 @@ +//===- StackSafetyAnalysis.h - Stack memory safety analysis -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Stack Safety Analysis detects allocas and arguments with safe access. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_STACKSAFETYANALYSIS_H +#define LLVM_ANALYSIS_STACKSAFETYANALYSIS_H + +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +namespace llvm { + +/// Interface to access stack safety analysis results for single function. +class StackSafetyInfo { +public: + struct FunctionInfo; + +private: + std::unique_ptr Info; + +public: + StackSafetyInfo(); + StackSafetyInfo(FunctionInfo &&Info); + StackSafetyInfo(StackSafetyInfo &&); + StackSafetyInfo &operator=(StackSafetyInfo &&); + ~StackSafetyInfo(); + + // TODO: Add useful for client methods. + void print(raw_ostream &O) const; +}; + +/// StackSafetyInfo wrapper for the new pass manager. +class StackSafetyAnalysis : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static AnalysisKey Key; + +public: + using Result = StackSafetyInfo; + StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Printer pass for the \c StackSafetyAnalysis results. +class StackSafetyPrinterPass : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit StackSafetyPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// StackSafetyInfo wrapper for the legacy pass manager +class StackSafetyInfoWrapperPass : public FunctionPass { + StackSafetyInfo SSI; + +public: + static char ID; + StackSafetyInfoWrapperPass(); + + const StackSafetyInfo &getResult() const { return SSI; } + + void print(raw_ostream &O, const Module *M) const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnFunction(Function &F) override; +}; + +using StackSafetyGlobalInfo = std::map; + +/// This pass performs the global (interprocedural) stack safety analysis (new +/// pass manager). +class StackSafetyGlobalAnalysis + : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static AnalysisKey Key; + +public: + using Result = StackSafetyGlobalInfo; + Result run(Module &M, ModuleAnalysisManager &AM); +}; + +/// Printer pass for the \c StackSafetyGlobalAnalysis results. +class StackSafetyGlobalPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +/// This pass performs the global (interprocedural) stack safety analysis +/// (legacy pass manager). +class StackSafetyGlobalInfoWrapperPass : public ModulePass { + StackSafetyGlobalInfo SSI; + +public: + static char ID; + + StackSafetyGlobalInfoWrapperPass(); + + const StackSafetyGlobalInfo &getResult() const { return SSI; } + + void print(raw_ostream &O, const Module *M) const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnModule(Module &M) override; +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H diff --git a/contrib/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h new file mode 100644 index 00000000000..df693d9d8e8 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h @@ -0,0 +1,86 @@ +//===- SyncDependenceAnalysis.h - Divergent Branch Dependence -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// \file +// This file defines the SyncDependenceAnalysis class, which computes for +// every divergent branch the set of phi nodes that the branch will make +// divergent. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H +#define LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/LoopInfo.h" +#include + +namespace llvm { + +class BasicBlock; +class DominatorTree; +class Loop; +class PostDominatorTree; + +using ConstBlockSet = SmallPtrSet; + +/// \brief Relates points of divergent control to join points in +/// reducible CFGs. +/// +/// This analysis relates points of divergent control to points of converging +/// divergent control. The analysis requires all loops to be reducible. +class SyncDependenceAnalysis { + void visitSuccessor(const BasicBlock &succBlock, const Loop *termLoop, + const BasicBlock *defBlock); + +public: + bool inRegion(const BasicBlock &BB) const; + + ~SyncDependenceAnalysis(); + SyncDependenceAnalysis(const DominatorTree &DT, const PostDominatorTree &PDT, + const LoopInfo &LI); + + /// \brief Computes divergent join points and loop exits caused by branch + /// divergence in \p Term. + /// + /// The set of blocks which are reachable by disjoint paths from \p Term. + /// The set also contains loop exits if there two disjoint paths: + /// one from \p Term to the loop exit and another from \p Term to the loop + /// header. Those exit blocks are added to the returned set. + /// If L is the parent loop of \p Term and an exit of L is in the returned + /// set then L is a divergent loop. + const ConstBlockSet &join_blocks(const Instruction &Term); + + /// \brief Computes divergent join points and loop exits (in the surrounding + /// loop) caused by the divergent loop exits of\p Loop. + /// + /// The set of blocks which are reachable by disjoint paths from the + /// loop exits of \p Loop. + /// This treats the loop as a single node in \p Loop's parent loop. + /// The returned set has the same properties as for join_blocks(TermInst&). + const ConstBlockSet &join_blocks(const Loop &Loop); + +private: + static ConstBlockSet EmptyBlockSet; + + ReversePostOrderTraversal FuncRPOT; + const DominatorTree &DT; + const PostDominatorTree &PDT; + const LoopInfo &LI; + + std::map> CachedLoopExitJoins; + std::map> + CachedBranchJoins; +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H diff --git a/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h b/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h index 87f4a0100b3..db80bef001e 100644 --- a/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h +++ b/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h @@ -36,16 +36,17 @@ public: using EdgeRef = typename CGT::EdgeRef; using SccTy = std::vector; - using GetRelBBFreqTy = function_ref(EdgeRef)>; - using GetCountTy = function_ref; - using AddCountTy = function_ref; + // Not all EdgeRef have information about the source of the edge. Hence + // NodeRef corresponding to the source of the EdgeRef is explicitly passed. + using GetProfCountTy = function_ref(NodeRef, EdgeRef)>; + using AddCountTy = function_ref; - static void propagate(const CallGraphType &CG, GetRelBBFreqTy GetRelBBFreq, - GetCountTy GetCount, AddCountTy AddCount); + static void propagate(const CallGraphType &CG, GetProfCountTy GetProfCount, + AddCountTy AddCount); private: - static void propagateFromSCC(const SccTy &SCC, GetRelBBFreqTy GetRelBBFreq, - GetCountTy GetCount, AddCountTy AddCount); + static void propagateFromSCC(const SccTy &SCC, GetProfCountTy GetProfCount, + AddCountTy AddCount); }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def index f94debba9c5..518a85ee1a0 100644 --- a/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -565,6 +565,30 @@ TLI_DEFINE_STRING_INTERNAL("cosl") /// char *ctermid(char *s); TLI_DEFINE_ENUM_INTERNAL(ctermid) TLI_DEFINE_STRING_INTERNAL("ctermid") +/// int execl(const char *path, const char *arg, ...); +TLI_DEFINE_ENUM_INTERNAL(execl) +TLI_DEFINE_STRING_INTERNAL("execl") +/// int execle(const char *file, const char *arg, ..., char * const envp[]); +TLI_DEFINE_ENUM_INTERNAL(execle) +TLI_DEFINE_STRING_INTERNAL("execle") +/// int execlp(const char *file, const char *arg, ...); +TLI_DEFINE_ENUM_INTERNAL(execlp) +TLI_DEFINE_STRING_INTERNAL("execlp") +/// int execv(const char *path, char *const argv[]); +TLI_DEFINE_ENUM_INTERNAL(execv) +TLI_DEFINE_STRING_INTERNAL("execv") +/// int execvP(const char *file, const char *search_path, char *const argv[]); +TLI_DEFINE_ENUM_INTERNAL(execvP) +TLI_DEFINE_STRING_INTERNAL("execvP") +/// int execve(const char *filename, char *const argv[], char *const envp[]); +TLI_DEFINE_ENUM_INTERNAL(execve) +TLI_DEFINE_STRING_INTERNAL("execve") +/// int execvp(const char *file, char *const argv[]); +TLI_DEFINE_ENUM_INTERNAL(execvp) +TLI_DEFINE_STRING_INTERNAL("execvp") +/// int execvpe(const char *file, char *const argv[], char *const envp[]); +TLI_DEFINE_ENUM_INTERNAL(execvpe) +TLI_DEFINE_STRING_INTERNAL("execvpe") /// double exp(double x); TLI_DEFINE_ENUM_INTERNAL(exp) TLI_DEFINE_STRING_INTERNAL("exp") @@ -709,6 +733,9 @@ TLI_DEFINE_STRING_INTERNAL("fopen") /// FILE *fopen64(const char *filename, const char *opentype) TLI_DEFINE_ENUM_INTERNAL(fopen64) TLI_DEFINE_STRING_INTERNAL("fopen64") +/// int fork(); +TLI_DEFINE_ENUM_INTERNAL(fork) +TLI_DEFINE_STRING_INTERNAL("fork") /// int fprintf(FILE *stream, const char *format, ...); TLI_DEFINE_ENUM_INTERNAL(fprintf) TLI_DEFINE_STRING_INTERNAL("fprintf") diff --git a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h index 59657cca40f..223175d17c2 100644 --- a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -289,7 +289,7 @@ public: /// Returns whether V is a source of divergence. /// /// This function provides the target-dependent information for - /// the target-independent DivergenceAnalysis. DivergenceAnalysis first + /// the target-independent LegacyDivergenceAnalysis. LegacyDivergenceAnalysis first /// builds the dependency graph, and then runs the reachability algorithm /// starting with the sources of divergence. bool isSourceOfDivergence(const Value *V) const; @@ -581,12 +581,21 @@ public: struct MemCmpExpansionOptions { // The list of available load sizes (in bytes), sorted in decreasing order. SmallVector LoadSizes; + // Set to true to allow overlapping loads. For example, 7-byte compares can + // be done with two 4-byte compares instead of 4+2+1-byte compares. This + // requires all loads in LoadSizes to be doable in an unaligned way. + bool AllowOverlappingLoads = false; }; const MemCmpExpansionOptions *enableMemCmpExpansion(bool IsZeroCmp) const; /// Enable matching of interleaved access groups. bool enableInterleavedAccessVectorization() const; + /// Enable matching of interleaved access groups that contain predicated + /// accesses or gaps and therefore vectorized using masked + /// vector loads/stores. + bool enableMaskedInterleavedAccessVectorization() const; + /// Indicate that it is potentially unsafe to automatically vectorize /// floating-point operations because the semantics of vector and scalar /// floating-point semantics may differ. For example, ARM NEON v7 SIMD math @@ -739,6 +748,10 @@ public: /// and the number of execution units in the CPU. unsigned getMaxInterleaveFactor(unsigned VF) const; + /// Collect properties of V used in cost analysis, e.g. OP_PowerOf2. + static OperandValueKind getOperandInfo(Value *V, + OperandValueProperties &OpProps); + /// This is an approximation of reciprocal throughput of a math/logic op. /// A higher cost indicates less expected throughput. /// From Agner Fog's guides, reciprocal throughput is "the average number of @@ -762,7 +775,9 @@ public: /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and - /// extraction shuffle kinds. + /// extraction shuffle kinds to show the insert/extract point and the type of + /// the subvector being inserted/extracted. + /// NOTE: For subvector extractions Tp represents the source type. int getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, Type *SubTp = nullptr) const; @@ -817,9 +832,13 @@ public: /// load allows gaps) /// \p Alignment is the alignment of the memory operation /// \p AddressSpace is address space of the pointer. + /// \p UseMaskForCond indicates if the memory access is predicated. + /// \p UseMaskForGaps indicates if gaps should be masked. int getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef Indices, unsigned Alignment, - unsigned AddressSpace) const; + unsigned AddressSpace, + bool UseMaskForCond = false, + bool UseMaskForGaps = false) const; /// Calculate the cost of performing a vector reduction. /// @@ -915,6 +934,14 @@ public: bool areInlineCompatible(const Function *Caller, const Function *Callee) const; + /// \returns True if the caller and callee agree on how \p Args will be passed + /// to the callee. + /// \param[out] Args The list of compatible arguments. The implementation may + /// filter out any incompatible args from this list. + bool areFunctionArgsABICompatible(const Function *Caller, + const Function *Callee, + SmallPtrSetImpl &Args) const; + /// The type of load/store indexing. enum MemIndexedMode { MIM_Unindexed, ///< No indexing. @@ -1068,6 +1095,7 @@ public: virtual const MemCmpExpansionOptions *enableMemCmpExpansion( bool IsZeroCmp) const = 0; virtual bool enableInterleavedAccessVectorization() = 0; + virtual bool enableMaskedInterleavedAccessVectorization() = 0; virtual bool isFPVectorizationPotentiallyUnsafe() = 0; virtual bool allowsMisalignedMemoryAccesses(LLVMContext &Context, unsigned BitWidth, @@ -1128,7 +1156,9 @@ public: unsigned Factor, ArrayRef Indices, unsigned Alignment, - unsigned AddressSpace) = 0; + unsigned AddressSpace, + bool UseMaskForCond = false, + bool UseMaskForGaps = false) = 0; virtual int getArithmeticReductionCost(unsigned Opcode, Type *Ty, bool IsPairwiseForm) = 0; virtual int getMinMaxReductionCost(Type *Ty, Type *CondTy, @@ -1157,6 +1187,9 @@ public: unsigned RemainingBytes, unsigned SrcAlign, unsigned DestAlign) const = 0; virtual bool areInlineCompatible(const Function *Caller, const Function *Callee) const = 0; + virtual bool + areFunctionArgsABICompatible(const Function *Caller, const Function *Callee, + SmallPtrSetImpl &Args) const = 0; virtual bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const = 0; virtual bool isIndexedStoreLegal(MemIndexedMode Mode,Type *Ty) const = 0; virtual unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const = 0; @@ -1342,6 +1375,9 @@ public: bool enableInterleavedAccessVectorization() override { return Impl.enableInterleavedAccessVectorization(); } + bool enableMaskedInterleavedAccessVectorization() override { + return Impl.enableMaskedInterleavedAccessVectorization(); + } bool isFPVectorizationPotentiallyUnsafe() override { return Impl.isFPVectorizationPotentiallyUnsafe(); } @@ -1467,9 +1503,11 @@ public: } int getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef Indices, unsigned Alignment, - unsigned AddressSpace) override { + unsigned AddressSpace, bool UseMaskForCond, + bool UseMaskForGaps) override { return Impl.getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices, - Alignment, AddressSpace); + Alignment, AddressSpace, + UseMaskForCond, UseMaskForGaps); } int getArithmeticReductionCost(unsigned Opcode, Type *Ty, bool IsPairwiseForm) override { @@ -1530,6 +1568,11 @@ public: const Function *Callee) const override { return Impl.areInlineCompatible(Caller, Callee); } + bool areFunctionArgsABICompatible( + const Function *Caller, const Function *Callee, + SmallPtrSetImpl &Args) const override { + return Impl.areFunctionArgsABICompatible(Caller, Callee, Args); + } bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const override { return Impl.isIndexedLoadLegal(Mode, Ty, getDataLayout()); } diff --git a/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index d80ae1d6845..c9a234deeb7 100644 --- a/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -158,6 +158,9 @@ public: case Intrinsic::dbg_label: case Intrinsic::invariant_start: case Intrinsic::invariant_end: + case Intrinsic::launder_invariant_group: + case Intrinsic::strip_invariant_group: + case Intrinsic::is_constant: case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: case Intrinsic::objectsize: @@ -311,6 +314,8 @@ public: bool enableInterleavedAccessVectorization() { return false; } + bool enableMaskedInterleavedAccessVectorization() { return false; } + bool isFPVectorizationPotentiallyUnsafe() { return false; } bool allowsMisalignedMemoryAccesses(LLVMContext &Context, @@ -448,8 +453,9 @@ public: unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef Indices, - unsigned Alignment, - unsigned AddressSpace) { + unsigned Alignment, unsigned AddressSpace, + bool UseMaskForCond = false, + bool UseMaskForGaps = false) { return 1; } @@ -520,6 +526,14 @@ public: Callee->getFnAttribute("target-features")); } + bool areFunctionArgsABICompatible(const Function *Caller, const Function *Callee, + SmallPtrSetImpl &Args) const { + return (Caller->getFnAttribute("target-cpu") == + Callee->getFnAttribute("target-cpu")) && + (Caller->getFnAttribute("target-features") == + Callee->getFnAttribute("target-features")); + } + bool isIndexedLoadLegal(TTI::MemIndexedMode Mode, Type *Ty, const DataLayout &DL) const { return false; diff --git a/contrib/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h index 7fcfdb3a817..d2e6df22425 100644 --- a/contrib/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h @@ -17,7 +17,7 @@ #define LLVM_ANALYSIS_TYPEBASEDALIASANALYSIS_H #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/IR/CallSite.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include @@ -43,10 +43,10 @@ public: AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal); - FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS); + FunctionModRefBehavior getModRefBehavior(const CallBase *Call); FunctionModRefBehavior getModRefBehavior(const Function *F); - ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc); - ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); private: bool Aliases(const MDNode *A, const MDNode *B) const; diff --git a/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h b/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h index 6764563f683..3bf9c5d2074 100644 --- a/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h +++ b/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h @@ -20,6 +20,8 @@ namespace llvm { +class DominatorTree; + /// The type of CFI jumptable needed for a function. enum CfiFunctionLinkage { CFL_Definition = 0, @@ -39,7 +41,8 @@ struct DevirtCallSite { /// call sites based on the call and return them in DevirtCalls. void findDevirtualizableCallsForTypeTest( SmallVectorImpl &DevirtCalls, - SmallVectorImpl &Assumes, const CallInst *CI); + SmallVectorImpl &Assumes, const CallInst *CI, + DominatorTree &DT); /// Given a call to the intrinsic \@llvm.type.checked.load, find all /// devirtualizable call sites based on the call and return them in DevirtCalls. @@ -47,7 +50,7 @@ void findDevirtualizableCallsForTypeCheckedLoad( SmallVectorImpl &DevirtCalls, SmallVectorImpl &LoadedPtrs, SmallVectorImpl &Preds, bool &HasNonCallUses, - const CallInst *CI); + const CallInst *CI, DominatorTree &DT); } #endif diff --git a/contrib/llvm/include/llvm/Analysis/ValueTracking.h b/contrib/llvm/include/llvm/Analysis/ValueTracking.h index c1a91a8e598..f46fdfcb608 100644 --- a/contrib/llvm/include/llvm/Analysis/ValueTracking.h +++ b/contrib/llvm/include/llvm/Analysis/ValueTracking.h @@ -55,14 +55,16 @@ class Value; AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr, - OptimizationRemarkEmitter *ORE = nullptr); + OptimizationRemarkEmitter *ORE = nullptr, + bool UseInstrInfo = true); /// Returns the known bits rather than passing by reference. KnownBits computeKnownBits(const Value *V, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr, - OptimizationRemarkEmitter *ORE = nullptr); + OptimizationRemarkEmitter *ORE = nullptr, + bool UseInstrInfo = true); /// Compute known bits from the range metadata. /// \p KnownZero the set of bits that are known to be zero @@ -75,7 +77,8 @@ class Value; const DataLayout &DL, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// Return true if the given value is known to have exactly one bit set when /// defined. For vectors return true if every element is known to be a power @@ -86,7 +89,8 @@ class Value; bool OrZero = false, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI); @@ -99,7 +103,8 @@ class Value; bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// Return true if the two given values are negation. /// Currently can recoginze Value pair: @@ -112,28 +117,32 @@ class Value; unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// Returns true if the given value is known be positive (i.e. non-negative /// and non-zero). bool isKnownPositive(const Value *V, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// Returns true if the given value is known be negative (i.e. non-positive /// and non-zero). bool isKnownNegative(const Value *V, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// Return true if the given values are known to be non-equal when defined. /// Supports scalar integer types only. bool isKnownNonEqual(const Value *V1, const Value *V2, const DataLayout &DL, - AssumptionCache *AC = nullptr, - const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// Return true if 'V & Mask' is known to be zero. We use this predicate to /// simplify operations downstream. Mask is known to be zero for bits that V @@ -148,7 +157,8 @@ class Value; const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// Return the number of times the sign bit of the register is replicated into /// the other bits. We know that at least 1 bit is always equal to the sign @@ -160,7 +170,8 @@ class Value; unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseInstrInfo = true); /// This function computes the integer multiple of Base that equals V. If /// successful, it returns true and returns the multiple in Multiple. If @@ -194,7 +205,8 @@ class Value; /// Return true if the floating-point scalar value is not a NaN or if the /// floating-point vector value has no NaN elements. Return false if a value /// could ever be NaN. - bool isKnownNeverNaN(const Value *V); + bool isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI, + unsigned Depth = 0); /// Return true if we can prove that the specified FP value's sign bit is 0. /// @@ -209,7 +221,8 @@ class Value; /// return the i8 value that it is represented with. This is true for all i8 /// values obviously, but is also true for i32 0, i32 -1, i16 0xF0F0, double /// 0.0 etc. If the value can't be handled with a repeated byte store (e.g. - /// i16 0x1234), return null. + /// i16 0x1234), return null. If the value is entirely undef and padding, + /// return undef. Value *isBytewiseValue(Value *V); /// Given an aggregrate and an sequence of indices, see if the scalar value @@ -284,10 +297,10 @@ class Value; /// This function returns call pointer argument that is considered the same by /// aliasing rules. You CAN'T use it to replace one value with another. - const Value *getArgumentAliasingToReturnedPointer(ImmutableCallSite CS); - inline Value *getArgumentAliasingToReturnedPointer(CallSite CS) { - return const_cast( - getArgumentAliasingToReturnedPointer(ImmutableCallSite(CS))); + const Value *getArgumentAliasingToReturnedPointer(const CallBase *Call); + inline Value *getArgumentAliasingToReturnedPointer(CallBase *Call) { + return const_cast(getArgumentAliasingToReturnedPointer( + const_cast(Call))); } // {launder,strip}.invariant.group returns pointer that aliases its argument, @@ -296,7 +309,7 @@ class Value; // considered as capture. The arguments are not marked as returned neither, // because it would make it useless. bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing( - ImmutableCallSite CS); + const CallBase *Call); /// This method strips off any GEP address adjustments and pointer casts from /// the specified value, returning the original object being addressed. Note @@ -405,18 +418,21 @@ class Value; const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, - const DominatorTree *DT); + const DominatorTree *DT, + bool UseInstrInfo = true); OverflowResult computeOverflowForSignedMul(const Value *LHS, const Value *RHS, const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, - const DominatorTree *DT); + const DominatorTree *DT, + bool UseInstrInfo = true); OverflowResult computeOverflowForUnsignedAdd(const Value *LHS, const Value *RHS, const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, - const DominatorTree *DT); + const DominatorTree *DT, + bool UseInstrInfo = true); OverflowResult computeOverflowForSignedAdd(const Value *LHS, const Value *RHS, const DataLayout &DL, AssumptionCache *AC = nullptr, @@ -594,6 +610,12 @@ class Value; Optional isImpliedCondition(const Value *LHS, const Value *RHS, const DataLayout &DL, bool LHSIsTrue = true, unsigned Depth = 0); + + /// Return the boolean condition value in the context of the given instruction + /// if it is known based on dominating conditions. + Optional isImpliedByDomCondition(const Value *Cond, + const Instruction *ContextI, + const DataLayout &DL); } // end namespace llvm #endif // LLVM_ANALYSIS_VALUETRACKING_H diff --git a/contrib/llvm/include/llvm/Analysis/VectorUtils.h b/contrib/llvm/include/llvm/Analysis/VectorUtils.h index 9fde36d6109..be4d4f17b9a 100644 --- a/contrib/llvm/include/llvm/Analysis/VectorUtils.h +++ b/contrib/llvm/include/llvm/Analysis/VectorUtils.h @@ -15,6 +15,7 @@ #define LLVM_ANALYSIS_VECTORUTILS_H #include "llvm/ADT/MapVector.h" +#include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/IRBuilder.h" @@ -23,6 +24,7 @@ namespace llvm { template class ArrayRef; class DemandedBits; class GetElementPtrInst; +template class InterleaveGroup; class Loop; class ScalarEvolution; class TargetTransformInfo; @@ -115,8 +117,24 @@ computeMinimumValueSizes(ArrayRef Blocks, DemandedBits &DB, const TargetTransformInfo *TTI=nullptr); +/// Compute the union of two access-group lists. +/// +/// If the list contains just one access group, it is returned directly. If the +/// list is empty, returns nullptr. +MDNode *uniteAccessGroups(MDNode *AccGroups1, MDNode *AccGroups2); + +/// Compute the access-group list of access groups that @p Inst1 and @p Inst2 +/// are both in. If either instruction does not access memory at all, it is +/// considered to be in every list. +/// +/// If the list contains just one access group, it is returned directly. If the +/// list is empty, returns nullptr. +MDNode *intersectAccessGroups(const Instruction *Inst1, + const Instruction *Inst2); + /// Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, -/// MD_nontemporal]. For K in Kinds, we get the MDNode for K from each of the +/// MD_nontemporal, MD_access_group]. +/// For K in Kinds, we get the MDNode for K from each of the /// elements of VL, compute their "intersection" (i.e., the most generic /// metadata value that covers all of the individual values), and set I's /// metadata for M equal to the intersection value. @@ -124,6 +142,35 @@ computeMinimumValueSizes(ArrayRef Blocks, /// This function always sets a (possibly null) value for each K in Kinds. Instruction *propagateMetadata(Instruction *I, ArrayRef VL); +/// Create a mask that filters the members of an interleave group where there +/// are gaps. +/// +/// For example, the mask for \p Group with interleave-factor 3 +/// and \p VF 4, that has only its first member present is: +/// +/// <1,0,0,1,0,0,1,0,0,1,0,0> +/// +/// Note: The result is a mask of 0's and 1's, as opposed to the other +/// create[*]Mask() utilities which create a shuffle mask (mask that +/// consists of indices). +Constant *createBitMaskForGaps(IRBuilder<> &Builder, unsigned VF, + const InterleaveGroup &Group); + +/// Create a mask with replicated elements. +/// +/// This function creates a shuffle mask for replicating each of the \p VF +/// elements in a vector \p ReplicationFactor times. It can be used to +/// transform a mask of \p VF elements into a mask of +/// \p VF * \p ReplicationFactor elements used by a predicated +/// interleaved-group of loads/stores whose Interleaved-factor == +/// \p ReplicationFactor. +/// +/// For example, the mask for \p ReplicationFactor=3 and \p VF=4 is: +/// +/// <0,0,0,1,1,1,2,2,2,3,3,3> +Constant *createReplicatedMask(IRBuilder<> &Builder, unsigned ReplicationFactor, + unsigned VF); + /// Create an interleave shuffle mask. /// /// This function creates a shuffle mask for interleaving \p NumVecs vectors of @@ -176,6 +223,381 @@ Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start, /// elements, it will be padded with undefs. Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef Vecs); +/// The group of interleaved loads/stores sharing the same stride and +/// close to each other. +/// +/// Each member in this group has an index starting from 0, and the largest +/// index should be less than interleaved factor, which is equal to the absolute +/// value of the access's stride. +/// +/// E.g. An interleaved load group of factor 4: +/// for (unsigned i = 0; i < 1024; i+=4) { +/// a = A[i]; // Member of index 0 +/// b = A[i+1]; // Member of index 1 +/// d = A[i+3]; // Member of index 3 +/// ... +/// } +/// +/// An interleaved store group of factor 4: +/// for (unsigned i = 0; i < 1024; i+=4) { +/// ... +/// A[i] = a; // Member of index 0 +/// A[i+1] = b; // Member of index 1 +/// A[i+2] = c; // Member of index 2 +/// A[i+3] = d; // Member of index 3 +/// } +/// +/// Note: the interleaved load group could have gaps (missing members), but +/// the interleaved store group doesn't allow gaps. +template class InterleaveGroup { +public: + InterleaveGroup(unsigned Factor, bool Reverse, unsigned Align) + : Factor(Factor), Reverse(Reverse), Align(Align), InsertPos(nullptr) {} + + InterleaveGroup(InstTy *Instr, int Stride, unsigned Align) + : Align(Align), InsertPos(Instr) { + assert(Align && "The alignment should be non-zero"); + + Factor = std::abs(Stride); + assert(Factor > 1 && "Invalid interleave factor"); + + Reverse = Stride < 0; + Members[0] = Instr; + } + + bool isReverse() const { return Reverse; } + unsigned getFactor() const { return Factor; } + unsigned getAlignment() const { return Align; } + unsigned getNumMembers() const { return Members.size(); } + + /// Try to insert a new member \p Instr with index \p Index and + /// alignment \p NewAlign. The index is related to the leader and it could be + /// negative if it is the new leader. + /// + /// \returns false if the instruction doesn't belong to the group. + bool insertMember(InstTy *Instr, int Index, unsigned NewAlign) { + assert(NewAlign && "The new member's alignment should be non-zero"); + + int Key = Index + SmallestKey; + + // Skip if there is already a member with the same index. + if (Members.find(Key) != Members.end()) + return false; + + if (Key > LargestKey) { + // The largest index is always less than the interleave factor. + if (Index >= static_cast(Factor)) + return false; + + LargestKey = Key; + } else if (Key < SmallestKey) { + // The largest index is always less than the interleave factor. + if (LargestKey - Key >= static_cast(Factor)) + return false; + + SmallestKey = Key; + } + + // It's always safe to select the minimum alignment. + Align = std::min(Align, NewAlign); + Members[Key] = Instr; + return true; + } + + /// Get the member with the given index \p Index + /// + /// \returns nullptr if contains no such member. + InstTy *getMember(unsigned Index) const { + int Key = SmallestKey + Index; + auto Member = Members.find(Key); + if (Member == Members.end()) + return nullptr; + + return Member->second; + } + + /// Get the index for the given member. Unlike the key in the member + /// map, the index starts from 0. + unsigned getIndex(const InstTy *Instr) const { + for (auto I : Members) { + if (I.second == Instr) + return I.first - SmallestKey; + } + + llvm_unreachable("InterleaveGroup contains no such member"); + } + + InstTy *getInsertPos() const { return InsertPos; } + void setInsertPos(InstTy *Inst) { InsertPos = Inst; } + + /// Add metadata (e.g. alias info) from the instructions in this group to \p + /// NewInst. + /// + /// FIXME: this function currently does not add noalias metadata a'la + /// addNewMedata. To do that we need to compute the intersection of the + /// noalias info from all members. + void addMetadata(InstTy *NewInst) const; + + /// Returns true if this Group requires a scalar iteration to handle gaps. + bool requiresScalarEpilogue() const { + // If the last member of the Group exists, then a scalar epilog is not + // needed for this group. + if (getMember(getFactor() - 1)) + return false; + + // We have a group with gaps. It therefore cannot be a group of stores, + // and it can't be a reversed access, because such groups get invalidated. + assert(!getMember(0)->mayWriteToMemory() && + "Group should have been invalidated"); + assert(!isReverse() && "Group should have been invalidated"); + + // This is a group of loads, with gaps, and without a last-member + return true; + } + +private: + unsigned Factor; // Interleave Factor. + bool Reverse; + unsigned Align; + DenseMap Members; + int SmallestKey = 0; + int LargestKey = 0; + + // To avoid breaking dependences, vectorized instructions of an interleave + // group should be inserted at either the first load or the last store in + // program order. + // + // E.g. %even = load i32 // Insert Position + // %add = add i32 %even // Use of %even + // %odd = load i32 + // + // store i32 %even + // %odd = add i32 // Def of %odd + // store i32 %odd // Insert Position + InstTy *InsertPos; +}; + +/// Drive the analysis of interleaved memory accesses in the loop. +/// +/// Use this class to analyze interleaved accesses only when we can vectorize +/// a loop. Otherwise it's meaningless to do analysis as the vectorization +/// on interleaved accesses is unsafe. +/// +/// The analysis collects interleave groups and records the relationships +/// between the member and the group in a map. +class InterleavedAccessInfo { +public: + InterleavedAccessInfo(PredicatedScalarEvolution &PSE, Loop *L, + DominatorTree *DT, LoopInfo *LI, + const LoopAccessInfo *LAI) + : PSE(PSE), TheLoop(L), DT(DT), LI(LI), LAI(LAI) {} + + ~InterleavedAccessInfo() { reset(); } + + /// Analyze the interleaved accesses and collect them in interleave + /// groups. Substitute symbolic strides using \p Strides. + /// Consider also predicated loads/stores in the analysis if + /// \p EnableMaskedInterleavedGroup is true. + void analyzeInterleaving(bool EnableMaskedInterleavedGroup); + + /// Invalidate groups, e.g., in case all blocks in loop will be predicated + /// contrary to original assumption. Although we currently prevent group + /// formation for predicated accesses, we may be able to relax this limitation + /// in the future once we handle more complicated blocks. + void reset() { + SmallPtrSet *, 4> DelSet; + // Avoid releasing a pointer twice. + for (auto &I : InterleaveGroupMap) + DelSet.insert(I.second); + for (auto *Ptr : DelSet) + delete Ptr; + InterleaveGroupMap.clear(); + RequiresScalarEpilogue = false; + } + + + /// Check if \p Instr belongs to any interleave group. + bool isInterleaved(Instruction *Instr) const { + return InterleaveGroupMap.find(Instr) != InterleaveGroupMap.end(); + } + + /// Get the interleave group that \p Instr belongs to. + /// + /// \returns nullptr if doesn't have such group. + InterleaveGroup * + getInterleaveGroup(const Instruction *Instr) const { + if (InterleaveGroupMap.count(Instr)) + return InterleaveGroupMap.find(Instr)->second; + return nullptr; + } + + iterator_range *>> + getInterleaveGroups() { + return make_range(InterleaveGroups.begin(), InterleaveGroups.end()); + } + + /// Returns true if an interleaved group that may access memory + /// out-of-bounds requires a scalar epilogue iteration for correctness. + bool requiresScalarEpilogue() const { return RequiresScalarEpilogue; } + + /// Invalidate groups that require a scalar epilogue (due to gaps). This can + /// happen when optimizing for size forbids a scalar epilogue, and the gap + /// cannot be filtered by masking the load/store. + void invalidateGroupsRequiringScalarEpilogue(); + +private: + /// A wrapper around ScalarEvolution, used to add runtime SCEV checks. + /// Simplifies SCEV expressions in the context of existing SCEV assumptions. + /// The interleaved access analysis can also add new predicates (for example + /// by versioning strides of pointers). + PredicatedScalarEvolution &PSE; + + Loop *TheLoop; + DominatorTree *DT; + LoopInfo *LI; + const LoopAccessInfo *LAI; + + /// True if the loop may contain non-reversed interleaved groups with + /// out-of-bounds accesses. We ensure we don't speculatively access memory + /// out-of-bounds by executing at least one scalar epilogue iteration. + bool RequiresScalarEpilogue = false; + + /// Holds the relationships between the members and the interleave group. + DenseMap *> InterleaveGroupMap; + + SmallPtrSet *, 4> InterleaveGroups; + + /// Holds dependences among the memory accesses in the loop. It maps a source + /// access to a set of dependent sink accesses. + DenseMap> Dependences; + + /// The descriptor for a strided memory access. + struct StrideDescriptor { + StrideDescriptor() = default; + StrideDescriptor(int64_t Stride, const SCEV *Scev, uint64_t Size, + unsigned Align) + : Stride(Stride), Scev(Scev), Size(Size), Align(Align) {} + + // The access's stride. It is negative for a reverse access. + int64_t Stride = 0; + + // The scalar expression of this access. + const SCEV *Scev = nullptr; + + // The size of the memory object. + uint64_t Size = 0; + + // The alignment of this access. + unsigned Align = 0; + }; + + /// A type for holding instructions and their stride descriptors. + using StrideEntry = std::pair; + + /// Create a new interleave group with the given instruction \p Instr, + /// stride \p Stride and alignment \p Align. + /// + /// \returns the newly created interleave group. + InterleaveGroup * + createInterleaveGroup(Instruction *Instr, int Stride, unsigned Align) { + assert(!InterleaveGroupMap.count(Instr) && + "Already in an interleaved access group"); + InterleaveGroupMap[Instr] = + new InterleaveGroup(Instr, Stride, Align); + InterleaveGroups.insert(InterleaveGroupMap[Instr]); + return InterleaveGroupMap[Instr]; + } + + /// Release the group and remove all the relationships. + void releaseGroup(InterleaveGroup *Group) { + for (unsigned i = 0; i < Group->getFactor(); i++) + if (Instruction *Member = Group->getMember(i)) + InterleaveGroupMap.erase(Member); + + InterleaveGroups.erase(Group); + delete Group; + } + + /// Collect all the accesses with a constant stride in program order. + void collectConstStrideAccesses( + MapVector &AccessStrideInfo, + const ValueToValueMap &Strides); + + /// Returns true if \p Stride is allowed in an interleaved group. + static bool isStrided(int Stride); + + /// Returns true if \p BB is a predicated block. + bool isPredicated(BasicBlock *BB) const { + return LoopAccessInfo::blockNeedsPredication(BB, TheLoop, DT); + } + + /// Returns true if LoopAccessInfo can be used for dependence queries. + bool areDependencesValid() const { + return LAI && LAI->getDepChecker().getDependences(); + } + + /// Returns true if memory accesses \p A and \p B can be reordered, if + /// necessary, when constructing interleaved groups. + /// + /// \p A must precede \p B in program order. We return false if reordering is + /// not necessary or is prevented because \p A and \p B may be dependent. + bool canReorderMemAccessesForInterleavedGroups(StrideEntry *A, + StrideEntry *B) const { + // Code motion for interleaved accesses can potentially hoist strided loads + // and sink strided stores. The code below checks the legality of the + // following two conditions: + // + // 1. Potentially moving a strided load (B) before any store (A) that + // precedes B, or + // + // 2. Potentially moving a strided store (A) after any load or store (B) + // that A precedes. + // + // It's legal to reorder A and B if we know there isn't a dependence from A + // to B. Note that this determination is conservative since some + // dependences could potentially be reordered safely. + + // A is potentially the source of a dependence. + auto *Src = A->first; + auto SrcDes = A->second; + + // B is potentially the sink of a dependence. + auto *Sink = B->first; + auto SinkDes = B->second; + + // Code motion for interleaved accesses can't violate WAR dependences. + // Thus, reordering is legal if the source isn't a write. + if (!Src->mayWriteToMemory()) + return true; + + // At least one of the accesses must be strided. + if (!isStrided(SrcDes.Stride) && !isStrided(SinkDes.Stride)) + return true; + + // If dependence information is not available from LoopAccessInfo, + // conservatively assume the instructions can't be reordered. + if (!areDependencesValid()) + return false; + + // If we know there is a dependence from source to sink, assume the + // instructions can't be reordered. Otherwise, reordering is legal. + return Dependences.find(Src) == Dependences.end() || + !Dependences.lookup(Src).count(Sink); + } + + /// Collect the dependences from LoopAccessInfo. + /// + /// We process the dependences once during the interleaved access analysis to + /// enable constant-time dependence queries. + void collectDependences() { + if (!areDependencesValid()) + return; + auto *Deps = LAI->getDepChecker().getDependences(); + for (auto Dep : *Deps) + Dependences[Dep.getSource(*LAI)].insert(Dep.getDestination(*LAI)); + } +}; + } // llvm namespace #endif diff --git a/contrib/llvm/include/llvm/BinaryFormat/AMDGPUMetadataVerifier.h b/contrib/llvm/include/llvm/BinaryFormat/AMDGPUMetadataVerifier.h new file mode 100644 index 00000000000..de44f41720e --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/AMDGPUMetadataVerifier.h @@ -0,0 +1,70 @@ +//===- AMDGPUMetadataVerifier.h - MsgPack Types -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This is a verifier for AMDGPU HSA metadata, which can verify both +/// well-typed metadata and untyped metadata. When verifying in the non-strict +/// mode, untyped metadata is coerced into the correct type if possible. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H +#define LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H + +#include "llvm/BinaryFormat/MsgPackTypes.h" + +namespace llvm { +namespace AMDGPU { +namespace HSAMD { +namespace V3 { + +/// Verifier for AMDGPU HSA metadata. +/// +/// Operates in two modes: +/// +/// In strict mode, metadata must already be well-typed. +/// +/// In non-strict mode, metadata is coerced into expected types when possible. +class MetadataVerifier { + bool Strict; + + bool verifyScalar(msgpack::Node &Node, msgpack::ScalarNode::ScalarKind SKind, + function_ref verifyValue = {}); + bool verifyInteger(msgpack::Node &Node); + bool verifyArray(msgpack::Node &Node, + function_ref verifyNode, + Optional Size = None); + bool verifyEntry(msgpack::MapNode &MapNode, StringRef Key, bool Required, + function_ref verifyNode); + bool + verifyScalarEntry(msgpack::MapNode &MapNode, StringRef Key, bool Required, + msgpack::ScalarNode::ScalarKind SKind, + function_ref verifyValue = {}); + bool verifyIntegerEntry(msgpack::MapNode &MapNode, StringRef Key, + bool Required); + bool verifyKernelArgs(msgpack::Node &Node); + bool verifyKernel(msgpack::Node &Node); + +public: + /// Construct a MetadataVerifier, specifying whether it will operate in \p + /// Strict mode. + MetadataVerifier(bool Strict) : Strict(Strict) {} + + /// Verify given HSA metadata. + /// + /// \returns True when successful, false when metadata is invalid. + bool verify(msgpack::Node &HSAMetadataRoot); +}; + +} // end namespace V3 +} // end namespace HSAMD +} // end namespace AMDGPU +} // end namespace llvm + +#endif // LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H diff --git a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def index 944c5dd1c15..6ad3cb57f62 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -18,9 +18,11 @@ defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \ defined HANDLE_DW_CC || defined HANDLE_DW_LNS || defined HANDLE_DW_LNE || \ defined HANDLE_DW_LNCT || defined HANDLE_DW_MACRO || \ - defined HANDLE_DW_RLE || defined HANDLE_DW_CFA || \ + defined HANDLE_DW_RLE || \ + (defined HANDLE_DW_CFA && defined HANDLE_DW_CFA_PRED) || \ defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \ - defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX) + defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX || \ + defined HANDLE_DW_END) #error "Missing macro definition of HANDLE_DW*" #endif @@ -41,7 +43,7 @@ #endif #ifndef HANDLE_DW_LANG -#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) +#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) #endif #ifndef HANDLE_DW_ATE @@ -84,6 +86,10 @@ #define HANDLE_DW_CFA(ID, NAME) #endif +#ifndef HANDLE_DW_CFA_PRED +#define HANDLE_DW_CFA_PRED(ID, NAME, PRED) +#endif + #ifndef HANDLE_DW_APPLE_PROPERTY #define HANDLE_DW_APPLE_PROPERTY(ID, NAME) #endif @@ -100,6 +106,10 @@ #define HANDLE_DW_IDX(ID, NAME) #endif +#ifndef HANDLE_DW_END +#define HANDLE_DW_END(ID, NAME) +#endif + HANDLE_DW_TAG(0x0000, null, 2, DWARF) HANDLE_DW_TAG(0x0001, array_type, 2, DWARF) HANDLE_DW_TAG(0x0002, class_type, 2, DWARF) @@ -622,50 +632,50 @@ HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU) HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU) // DWARF languages. -HANDLE_DW_LANG(0x0001, C89, 2, DWARF) -HANDLE_DW_LANG(0x0002, C, 2, DWARF) -HANDLE_DW_LANG(0x0003, Ada83, 2, DWARF) -HANDLE_DW_LANG(0x0004, C_plus_plus, 2, DWARF) -HANDLE_DW_LANG(0x0005, Cobol74, 2, DWARF) -HANDLE_DW_LANG(0x0006, Cobol85, 2, DWARF) -HANDLE_DW_LANG(0x0007, Fortran77, 2, DWARF) -HANDLE_DW_LANG(0x0008, Fortran90, 2, DWARF) -HANDLE_DW_LANG(0x0009, Pascal83, 2, DWARF) -HANDLE_DW_LANG(0x000a, Modula2, 2, DWARF) +HANDLE_DW_LANG(0x0001, C89, 0, 2, DWARF) +HANDLE_DW_LANG(0x0002, C, 0, 2, DWARF) +HANDLE_DW_LANG(0x0003, Ada83, 1, 2, DWARF) +HANDLE_DW_LANG(0x0004, C_plus_plus, 0, 2, DWARF) +HANDLE_DW_LANG(0x0005, Cobol74, 1, 2, DWARF) +HANDLE_DW_LANG(0x0006, Cobol85, 1, 2, DWARF) +HANDLE_DW_LANG(0x0007, Fortran77, 1, 2, DWARF) +HANDLE_DW_LANG(0x0008, Fortran90, 1, 2, DWARF) +HANDLE_DW_LANG(0x0009, Pascal83, 1, 2, DWARF) +HANDLE_DW_LANG(0x000a, Modula2, 1, 2, DWARF) // New in DWARF v3: -HANDLE_DW_LANG(0x000b, Java, 3, DWARF) -HANDLE_DW_LANG(0x000c, C99, 3, DWARF) -HANDLE_DW_LANG(0x000d, Ada95, 3, DWARF) -HANDLE_DW_LANG(0x000e, Fortran95, 3, DWARF) -HANDLE_DW_LANG(0x000f, PLI, 3, DWARF) -HANDLE_DW_LANG(0x0010, ObjC, 3, DWARF) -HANDLE_DW_LANG(0x0011, ObjC_plus_plus, 3, DWARF) -HANDLE_DW_LANG(0x0012, UPC, 3, DWARF) -HANDLE_DW_LANG(0x0013, D, 3, DWARF) +HANDLE_DW_LANG(0x000b, Java, 0, 3, DWARF) +HANDLE_DW_LANG(0x000c, C99, 0, 3, DWARF) +HANDLE_DW_LANG(0x000d, Ada95, 1, 3, DWARF) +HANDLE_DW_LANG(0x000e, Fortran95, 1, 3, DWARF) +HANDLE_DW_LANG(0x000f, PLI, 1, 3, DWARF) +HANDLE_DW_LANG(0x0010, ObjC, 0, 3, DWARF) +HANDLE_DW_LANG(0x0011, ObjC_plus_plus, 0, 3, DWARF) +HANDLE_DW_LANG(0x0012, UPC, 0, 3, DWARF) +HANDLE_DW_LANG(0x0013, D, 0, 3, DWARF) // New in DWARF v4: -HANDLE_DW_LANG(0x0014, Python, 4, DWARF) +HANDLE_DW_LANG(0x0014, Python, 0, 4, DWARF) // New in DWARF v5: -HANDLE_DW_LANG(0x0015, OpenCL, 5, DWARF) -HANDLE_DW_LANG(0x0016, Go, 5, DWARF) -HANDLE_DW_LANG(0x0017, Modula3, 5, DWARF) -HANDLE_DW_LANG(0x0018, Haskell, 5, DWARF) -HANDLE_DW_LANG(0x0019, C_plus_plus_03, 5, DWARF) -HANDLE_DW_LANG(0x001a, C_plus_plus_11, 5, DWARF) -HANDLE_DW_LANG(0x001b, OCaml, 5, DWARF) -HANDLE_DW_LANG(0x001c, Rust, 5, DWARF) -HANDLE_DW_LANG(0x001d, C11, 5, DWARF) -HANDLE_DW_LANG(0x001e, Swift, 5, DWARF) -HANDLE_DW_LANG(0x001f, Julia, 5, DWARF) -HANDLE_DW_LANG(0x0020, Dylan, 5, DWARF) -HANDLE_DW_LANG(0x0021, C_plus_plus_14, 5, DWARF) -HANDLE_DW_LANG(0x0022, Fortran03, 5, DWARF) -HANDLE_DW_LANG(0x0023, Fortran08, 5, DWARF) -HANDLE_DW_LANG(0x0024, RenderScript, 5, DWARF) -HANDLE_DW_LANG(0x0025, BLISS, 5, DWARF) +HANDLE_DW_LANG(0x0015, OpenCL, 0, 5, DWARF) +HANDLE_DW_LANG(0x0016, Go, 0, 5, DWARF) +HANDLE_DW_LANG(0x0017, Modula3, 1, 5, DWARF) +HANDLE_DW_LANG(0x0018, Haskell, 0, 5, DWARF) +HANDLE_DW_LANG(0x0019, C_plus_plus_03, 0, 5, DWARF) +HANDLE_DW_LANG(0x001a, C_plus_plus_11, 0, 5, DWARF) +HANDLE_DW_LANG(0x001b, OCaml, 0, 5, DWARF) +HANDLE_DW_LANG(0x001c, Rust, 0, 5, DWARF) +HANDLE_DW_LANG(0x001d, C11, 0, 5, DWARF) +HANDLE_DW_LANG(0x001e, Swift, 0, 5, DWARF) +HANDLE_DW_LANG(0x001f, Julia, 1, 5, DWARF) +HANDLE_DW_LANG(0x0020, Dylan, 0, 5, DWARF) +HANDLE_DW_LANG(0x0021, C_plus_plus_14, 0, 5, DWARF) +HANDLE_DW_LANG(0x0022, Fortran03, 1, 5, DWARF) +HANDLE_DW_LANG(0x0023, Fortran08, 1, 5, DWARF) +HANDLE_DW_LANG(0x0024, RenderScript, 0, 5, DWARF) +HANDLE_DW_LANG(0x0025, BLISS, 0, 5, DWARF) // Vendor extensions: -HANDLE_DW_LANG(0x8001, Mips_Assembler, 0, MIPS) -HANDLE_DW_LANG(0x8e57, GOOGLE_RenderScript, 0, GOOGLE) -HANDLE_DW_LANG(0xb000, BORLAND_Delphi, 0, BORLAND) +HANDLE_DW_LANG(0x8001, Mips_Assembler, None, 0, MIPS) +HANDLE_DW_LANG(0x8e57, GOOGLE_RenderScript, 0, 0, GOOGLE) +HANDLE_DW_LANG(0xb000, BORLAND_Delphi, 0, 0, BORLAND) // DWARF attribute type encodings. HANDLE_DW_ATE(0x01, address, 2, DWARF) @@ -690,6 +700,11 @@ HANDLE_DW_ATE(0x10, UTF, 4, DWARF) HANDLE_DW_ATE(0x11, UCS, 5, DWARF) HANDLE_DW_ATE(0x12, ASCII, 5, DWARF) +// DWARF attribute endianity +HANDLE_DW_END(0x00, default) +HANDLE_DW_END(0x01, big) +HANDLE_DW_END(0x02, little) + // DWARF virtuality codes. HANDLE_DW_VIRTUALITY(0x00, none) HANDLE_DW_VIRTUALITY(0x01, virtual) @@ -821,9 +836,10 @@ HANDLE_DW_CFA(0x14, val_offset) HANDLE_DW_CFA(0x15, val_offset_sf) HANDLE_DW_CFA(0x16, val_expression) // Vendor extensions: -HANDLE_DW_CFA(0x1d, MIPS_advance_loc8) -HANDLE_DW_CFA(0x2d, GNU_window_save) -HANDLE_DW_CFA(0x2e, GNU_args_size) +HANDLE_DW_CFA_PRED(0x1d, MIPS_advance_loc8, SELECT_MIPS64) +HANDLE_DW_CFA_PRED(0x2d, GNU_window_save, SELECT_SPARC) +HANDLE_DW_CFA_PRED(0x2d, AARCH64_negate_ra_state, SELECT_AARCH64) +HANDLE_DW_CFA_PRED(0x2e, GNU_args_size, SELECT_X86) // Apple Objective-C Property Attributes. // Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind! @@ -863,6 +879,7 @@ HANDLE_DWARF_SECTION(DebugTypes, ".debug_types", "debug-types") HANDLE_DWARF_SECTION(DebugLine, ".debug_line", "debug-line") HANDLE_DWARF_SECTION(DebugLineStr, ".debug_line_str", "debug-line-str") HANDLE_DWARF_SECTION(DebugLoc, ".debug_loc", "debug-loc") +HANDLE_DWARF_SECTION(DebugLoclists, ".debug_loclists", "debug-loclists") HANDLE_DWARF_SECTION(DebugFrame, ".debug_frame", "debug-frame") HANDLE_DWARF_SECTION(DebugMacro, ".debug_macro", "debug-macro") HANDLE_DWARF_SECTION(DebugNames, ".debug_names", "debug-names") @@ -905,7 +922,9 @@ HANDLE_DW_IDX(0x05, type_hash) #undef HANDLE_DW_MACRO #undef HANDLE_DW_RLE #undef HANDLE_DW_CFA +#undef HANDLE_DW_CFA_PRED #undef HANDLE_DW_APPLE_PROPERTY #undef HANDLE_DW_UT #undef HANDLE_DWARF_SECTION #undef HANDLE_DW_IDX +#undef HANDLE_DW_END diff --git a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h index 9036f405eae..525a04d5e6c 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -26,6 +26,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadicDetails.h" +#include "llvm/ADT/Triple.h" namespace llvm { class StringRef; @@ -150,9 +151,8 @@ enum DecimalSignEncoding { enum EndianityEncoding { // Endianity attribute values - DW_END_default = 0x00, - DW_END_big = 0x01, - DW_END_little = 0x02, +#define HANDLE_DW_END(ID, NAME) DW_END_##NAME = ID, +#include "llvm/BinaryFormat/Dwarf.def" DW_END_lo_user = 0x40, DW_END_hi_user = 0xff }; @@ -184,7 +184,8 @@ enum DefaultedMemberAttribute { }; enum SourceLanguage { -#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) DW_LANG_##NAME = ID, +#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \ + DW_LANG_##NAME = ID, #include "llvm/BinaryFormat/Dwarf.def" DW_LANG_lo_user = 0x8000, DW_LANG_hi_user = 0xffff @@ -273,6 +274,7 @@ enum RangeListEntries { /// Call frame instruction encodings. enum CallFrameInfo { #define HANDLE_DW_CFA(ID, NAME) DW_CFA_##NAME = ID, +#define HANDLE_DW_CFA_PRED(ID, NAME, ARCH) DW_CFA_##NAME = ID, #include "llvm/BinaryFormat/Dwarf.def" DW_CFA_extended = 0x00, @@ -431,7 +433,7 @@ StringRef LNStandardString(unsigned Standard); StringRef LNExtendedString(unsigned Encoding); StringRef MacinfoString(unsigned Encoding); StringRef RangeListEncodingString(unsigned Encoding); -StringRef CallFrameString(unsigned Encoding); +StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch); StringRef ApplePropertyString(unsigned); StringRef UnitTypeString(unsigned); StringRef AtomTypeString(unsigned Atom); @@ -489,6 +491,8 @@ unsigned AttributeEncodingVendor(TypeKind E); unsigned LanguageVendor(SourceLanguage L); /// @} +Optional LanguageLowerBound(SourceLanguage L); + /// A helper struct providing information about the byte size of DW_FORM /// values that vary in size depending on the DWARF version, address byte /// size, or DWARF32/DWARF64. diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELF.h b/contrib/llvm/include/llvm/BinaryFormat/ELF.h index 2e778779117..ce35d127d43 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/ELF.h +++ b/contrib/llvm/include/llvm/BinaryFormat/ELF.h @@ -582,6 +582,7 @@ enum { EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60 EF_HEXAGON_MACH_V62 = 0x00000062, // Hexagon V62 EF_HEXAGON_MACH_V65 = 0x00000065, // Hexagon V65 + EF_HEXAGON_MACH_V66 = 0x00000066, // Hexagon V66 // Highest ISA version flags EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[11:0] @@ -594,6 +595,7 @@ enum { EF_HEXAGON_ISA_V60 = 0x00000060, // Hexagon V60 ISA EF_HEXAGON_ISA_V62 = 0x00000062, // Hexagon V62 ISA EF_HEXAGON_ISA_V65 = 0x00000065, // Hexagon V65 ISA + EF_HEXAGON_ISA_V66 = 0x00000066, // Hexagon V66 ISA }; // Hexagon-specific section indexes for common small data @@ -701,6 +703,7 @@ enum : unsigned { EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, + EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, // Reserved for AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_RESERVED0 = 0x027, @@ -708,11 +711,14 @@ enum : unsigned { // First/last AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, - EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX906, + EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX909, - // Indicates if the xnack target feature is enabled for all code contained in - // the object. + // Indicates if the "xnack" target feature is enabled for all code contained + // in the object. EF_AMDGPU_XNACK = 0x100, + // Indicates if the "sram-ecc" target feature is enabled for all code + // contained in the object. + EF_AMDGPU_SRAM_ECC = 0x200, }; // ELF Relocation types for AMDGPU @@ -725,6 +731,38 @@ enum { #include "ELFRelocs/BPF.def" }; +// MSP430 specific e_flags +enum : unsigned { + EF_MSP430_MACH_MSP430x11 = 11, + EF_MSP430_MACH_MSP430x11x1 = 110, + EF_MSP430_MACH_MSP430x12 = 12, + EF_MSP430_MACH_MSP430x13 = 13, + EF_MSP430_MACH_MSP430x14 = 14, + EF_MSP430_MACH_MSP430x15 = 15, + EF_MSP430_MACH_MSP430x16 = 16, + EF_MSP430_MACH_MSP430x20 = 20, + EF_MSP430_MACH_MSP430x22 = 22, + EF_MSP430_MACH_MSP430x23 = 23, + EF_MSP430_MACH_MSP430x24 = 24, + EF_MSP430_MACH_MSP430x26 = 26, + EF_MSP430_MACH_MSP430x31 = 31, + EF_MSP430_MACH_MSP430x32 = 32, + EF_MSP430_MACH_MSP430x33 = 33, + EF_MSP430_MACH_MSP430x41 = 41, + EF_MSP430_MACH_MSP430x42 = 42, + EF_MSP430_MACH_MSP430x43 = 43, + EF_MSP430_MACH_MSP430x44 = 44, + EF_MSP430_MACH_MSP430X = 45, + EF_MSP430_MACH_MSP430x46 = 46, + EF_MSP430_MACH_MSP430x47 = 47, + EF_MSP430_MACH_MSP430x54 = 54, +}; + +// ELF Relocation types for MSP430 +enum { +#include "ELFRelocs/MSP430.def" +}; + #undef ELF_RELOC // Section header. @@ -829,6 +867,8 @@ enum : unsigned { SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section. SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. + SHT_MSP430_ATTRIBUTES = 0x70000003U, + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. @@ -1321,7 +1361,7 @@ enum { GNU_PROPERTY_X86_FEATURE_1_SHSTK = 1 << 1 }; -// AMDGPU specific notes. +// AMD specific notes. (Code Object V2) enum { // Note types with values between 0 and 9 (inclusive) are reserved. NT_AMD_AMDGPU_HSA_METADATA = 10, @@ -1329,6 +1369,12 @@ enum { NT_AMD_AMDGPU_PAL_METADATA = 12 }; +// AMDGPU specific notes. (Code Object V3) +enum { + // Note types with values between 0 and 31 (inclusive) are reserved. + NT_AMDGPU_METADATA = 32 +}; + enum { GNU_ABI_TAG_LINUX = 0, GNU_ABI_TAG_HURD = 1, @@ -1339,6 +1385,8 @@ enum { GNU_ABI_TAG_NACL = 6, }; +constexpr const char *ELF_NOTE_GNU = "GNU"; + // Android packed relocation group flags. enum { RELOCATION_GROUPED_BY_INFO_FLAG = 1, diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/MSP430.def b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/MSP430.def new file mode 100644 index 00000000000..96990abf2db --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/MSP430.def @@ -0,0 +1,16 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_MSP430_NONE, 0) +ELF_RELOC(R_MSP430_32, 1) +ELF_RELOC(R_MSP430_10_PCREL, 2) +ELF_RELOC(R_MSP430_16, 3) +ELF_RELOC(R_MSP430_16_PCREL, 4) +ELF_RELOC(R_MSP430_16_BYTE, 5) +ELF_RELOC(R_MSP430_16_PCREL_BYTE, 6) +ELF_RELOC(R_MSP430_2X_PCREL, 7) +ELF_RELOC(R_MSP430_RL_PCREL, 8) +ELF_RELOC(R_MSP430_8, 9) +ELF_RELOC(R_MSP430_SYM_DIFF, 10) diff --git a/contrib/llvm/include/llvm/BinaryFormat/MachO.h b/contrib/llvm/include/llvm/BinaryFormat/MachO.h index c5294c76ebf..b3d60984249 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/MachO.h +++ b/contrib/llvm/include/llvm/BinaryFormat/MachO.h @@ -486,7 +486,10 @@ enum PlatformType { PLATFORM_IOS = 2, PLATFORM_TVOS = 3, PLATFORM_WATCHOS = 4, - PLATFORM_BRIDGEOS = 5 + PLATFORM_BRIDGEOS = 5, + PLATFORM_IOSSIMULATOR = 7, + PLATFORM_TVOSSIMULATOR = 8, + PLATFORM_WATCHOSSIMULATOR = 9 }; // Values for tools enum in build_tool_version. diff --git a/contrib/llvm/include/llvm/BinaryFormat/MsgPack.def b/contrib/llvm/include/llvm/BinaryFormat/MsgPack.def new file mode 100644 index 00000000000..781b49f46ae --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/MsgPack.def @@ -0,0 +1,108 @@ +//===- MsgPack.def - MessagePack definitions --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Macros for running through MessagePack enumerators. +/// +//===----------------------------------------------------------------------===// + +#if !( \ + defined HANDLE_MP_FIRST_BYTE || defined HANDLE_MP_FIX_BITS || \ + defined HANDLE_MP_FIX_BITS_MASK || defined HANDLE_MP_FIX_MAX || \ + defined HANDLE_MP_FIX_LEN || defined HANDLE_MP_FIX_MIN) +#error "Missing macro definition of HANDLE_MP*" +#endif + +#ifndef HANDLE_MP_FIRST_BYTE +#define HANDLE_MP_FIRST_BYTE(ID, NAME) +#endif + +#ifndef HANDLE_MP_FIX_BITS +#define HANDLE_MP_FIX_BITS(ID, NAME) +#endif + +#ifndef HANDLE_MP_FIX_BITS_MASK +#define HANDLE_MP_FIX_BITS_MASK(ID, NAME) +#endif + +#ifndef HANDLE_MP_FIX_MAX +#define HANDLE_MP_FIX_MAX(ID, NAME) +#endif + +#ifndef HANDLE_MP_FIX_LEN +#define HANDLE_MP_FIX_LEN(ID, NAME) +#endif + +#ifndef HANDLE_MP_FIX_MIN +#define HANDLE_MP_FIX_MIN(ID, NAME) +#endif + +HANDLE_MP_FIRST_BYTE(0xc0, Nil) +HANDLE_MP_FIRST_BYTE(0xc2, False) +HANDLE_MP_FIRST_BYTE(0xc3, True) +HANDLE_MP_FIRST_BYTE(0xc4, Bin8) +HANDLE_MP_FIRST_BYTE(0xc5, Bin16) +HANDLE_MP_FIRST_BYTE(0xc6, Bin32) +HANDLE_MP_FIRST_BYTE(0xc7, Ext8) +HANDLE_MP_FIRST_BYTE(0xc8, Ext16) +HANDLE_MP_FIRST_BYTE(0xc9, Ext32) +HANDLE_MP_FIRST_BYTE(0xca, Float32) +HANDLE_MP_FIRST_BYTE(0xcb, Float64) +HANDLE_MP_FIRST_BYTE(0xcc, UInt8) +HANDLE_MP_FIRST_BYTE(0xcd, UInt16) +HANDLE_MP_FIRST_BYTE(0xce, UInt32) +HANDLE_MP_FIRST_BYTE(0xcf, UInt64) +HANDLE_MP_FIRST_BYTE(0xd0, Int8) +HANDLE_MP_FIRST_BYTE(0xd1, Int16) +HANDLE_MP_FIRST_BYTE(0xd2, Int32) +HANDLE_MP_FIRST_BYTE(0xd3, Int64) +HANDLE_MP_FIRST_BYTE(0xd4, FixExt1) +HANDLE_MP_FIRST_BYTE(0xd5, FixExt2) +HANDLE_MP_FIRST_BYTE(0xd6, FixExt4) +HANDLE_MP_FIRST_BYTE(0xd7, FixExt8) +HANDLE_MP_FIRST_BYTE(0xd8, FixExt16) +HANDLE_MP_FIRST_BYTE(0xd9, Str8) +HANDLE_MP_FIRST_BYTE(0xda, Str16) +HANDLE_MP_FIRST_BYTE(0xdb, Str32) +HANDLE_MP_FIRST_BYTE(0xdc, Array16) +HANDLE_MP_FIRST_BYTE(0xdd, Array32) +HANDLE_MP_FIRST_BYTE(0xde, Map16) +HANDLE_MP_FIRST_BYTE(0xdf, Map32) + +HANDLE_MP_FIX_BITS(0x00, PositiveInt) +HANDLE_MP_FIX_BITS(0x80, Map) +HANDLE_MP_FIX_BITS(0x90, Array) +HANDLE_MP_FIX_BITS(0xa0, String) +HANDLE_MP_FIX_BITS(0xe0, NegativeInt) + +HANDLE_MP_FIX_BITS_MASK(0x80, PositiveInt) +HANDLE_MP_FIX_BITS_MASK(0xf0, Map) +HANDLE_MP_FIX_BITS_MASK(0xf0, Array) +HANDLE_MP_FIX_BITS_MASK(0xe0, String) +HANDLE_MP_FIX_BITS_MASK(0xe0, NegativeInt) + +HANDLE_MP_FIX_MAX(0x7f, PositiveInt) +HANDLE_MP_FIX_MAX(0x0f, Map) +HANDLE_MP_FIX_MAX(0x0f, Array) +HANDLE_MP_FIX_MAX(0x1f, String) + +HANDLE_MP_FIX_LEN(0x01, Ext1) +HANDLE_MP_FIX_LEN(0x02, Ext2) +HANDLE_MP_FIX_LEN(0x04, Ext4) +HANDLE_MP_FIX_LEN(0x08, Ext8) +HANDLE_MP_FIX_LEN(0x10, Ext16) + +HANDLE_MP_FIX_MIN(-0x20, NegativeInt) + +#undef HANDLE_MP_FIRST_BYTE +#undef HANDLE_MP_FIX_BITS +#undef HANDLE_MP_FIX_BITS_MASK +#undef HANDLE_MP_FIX_MAX +#undef HANDLE_MP_FIX_LEN +#undef HANDLE_MP_FIX_MIN diff --git a/contrib/llvm/include/llvm/BinaryFormat/MsgPack.h b/contrib/llvm/include/llvm/BinaryFormat/MsgPack.h new file mode 100644 index 00000000000..d431912a53e --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/MsgPack.h @@ -0,0 +1,93 @@ +//===-- MsgPack.h - MessagePack Constants -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains constants used for implementing MessagePack support. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_MSGPACK_H +#define LLVM_BINARYFORMAT_MSGPACK_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace msgpack { + +/// The endianness of all multi-byte encoded values in MessagePack. +constexpr support::endianness Endianness = support::big; + +/// The first byte identifiers of MessagePack object formats. +namespace FirstByte { +#define HANDLE_MP_FIRST_BYTE(ID, NAME) constexpr uint8_t NAME = ID; +#include "llvm/BinaryFormat/MsgPack.def" +} + +/// Most significant bits used to identify "Fix" variants in MessagePack. +/// +/// For example, FixStr objects encode their size in the five least significant +/// bits of their first byte, which is identified by the bit pattern "101" in +/// the three most significant bits. So FixBits::String contains 0b10100000. +/// +/// A corresponding mask of the bit pattern is found in \c FixBitsMask. +namespace FixBits { +#define HANDLE_MP_FIX_BITS(ID, NAME) constexpr uint8_t NAME = ID; +#include "llvm/BinaryFormat/MsgPack.def" +} + +/// Mask of bits used to identify "Fix" variants in MessagePack. +/// +/// For example, FixStr objects encode their size in the five least significant +/// bits of their first byte, which is identified by the bit pattern "101" in +/// the three most significant bits. So FixBitsMask::String contains +/// 0b11100000. +/// +/// The corresponding bit pattern to mask for is found in FixBits. +namespace FixBitsMask { +#define HANDLE_MP_FIX_BITS_MASK(ID, NAME) constexpr uint8_t NAME = ID; +#include "llvm/BinaryFormat/MsgPack.def" +} + +/// The maximum value or size encodable in "Fix" variants of formats. +/// +/// For example, FixStr objects encode their size in the five least significant +/// bits of their first byte, so the largest encodable size is 0b00011111. +namespace FixMax { +#define HANDLE_MP_FIX_MAX(ID, NAME) constexpr uint8_t NAME = ID; +#include "llvm/BinaryFormat/MsgPack.def" +} + +/// The exact size encodable in "Fix" variants of formats. +/// +/// The only objects for which an exact size makes sense are of Extension type. +/// +/// For example, FixExt4 stores an extension type containing exactly four bytes. +namespace FixLen { +#define HANDLE_MP_FIX_LEN(ID, NAME) constexpr uint8_t NAME = ID; +#include "llvm/BinaryFormat/MsgPack.def" +} + +/// The minimum value or size encodable in "Fix" variants of formats. +/// +/// The only object for which a minimum makes sense is a negative FixNum. +/// +/// Negative FixNum objects encode their signed integer value in one byte, but +/// they must have the pattern "111" as their three most significant bits. This +/// means all values are negative, and the smallest representable value is +/// 0b11100000. +namespace FixMin { +#define HANDLE_MP_FIX_MIN(ID, NAME) constexpr int8_t NAME = ID; +#include "llvm/BinaryFormat/MsgPack.def" +} + +} // end namespace msgpack +} // end namespace llvm + +#endif // LLVM_BINARYFORMAT_MSGPACK_H diff --git a/contrib/llvm/include/llvm/BinaryFormat/MsgPackReader.h b/contrib/llvm/include/llvm/BinaryFormat/MsgPackReader.h new file mode 100644 index 00000000000..511c3140745 --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/MsgPackReader.h @@ -0,0 +1,148 @@ +//===- MsgPackReader.h - Simple MsgPack reader ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This is a MessagePack reader. +/// +/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full +/// standard. +/// +/// Typical usage: +/// \code +/// StringRef input = GetInput(); +/// msgpack::Reader MPReader(input); +/// msgpack::Object Obj; +/// +/// while (MPReader.read(Obj)) { +/// switch (Obj.Kind) { +/// case msgpack::Type::Int: +// // Use Obj.Int +/// break; +/// // ... +/// } +/// } +/// \endcode +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MSGPACKREADER_H +#define LLVM_SUPPORT_MSGPACKREADER_H + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { +namespace msgpack { + +/// MessagePack types as defined in the standard, with the exception of Integer +/// being divided into a signed Int and unsigned UInt variant in order to map +/// directly to C++ types. +/// +/// The types map onto corresponding union members of the \c Object struct. +enum class Type : uint8_t { + Int, + UInt, + Nil, + Boolean, + Float, + String, + Binary, + Array, + Map, + Extension, +}; + +/// Extension types are composed of a user-defined type ID and an uninterpreted +/// sequence of bytes. +struct ExtensionType { + /// User-defined extension type. + int8_t Type; + /// Raw bytes of the extension object. + StringRef Bytes; +}; + +/// MessagePack object, represented as a tagged union of C++ types. +/// +/// All types except \c Type::Nil (which has only one value, and so is +/// completely represented by the \c Kind itself) map to a exactly one union +/// member. +struct Object { + Type Kind; + union { + /// Value for \c Type::Int. + int64_t Int; + /// Value for \c Type::Uint. + uint64_t UInt; + /// Value for \c Type::Boolean. + bool Bool; + /// Value for \c Type::Float. + double Float; + /// Value for \c Type::String and \c Type::Binary. + StringRef Raw; + /// Value for \c Type::Array and \c Type::Map. + size_t Length; + /// Value for \c Type::Extension. + ExtensionType Extension; + }; + + Object() : Kind(Type::Int), Int(0) {} +}; + +/// Reads MessagePack objects from memory, one at a time. +class Reader { +public: + /// Construct a reader, keeping a reference to the \p InputBuffer. + Reader(MemoryBufferRef InputBuffer); + /// Construct a reader, keeping a reference to the \p Input. + Reader(StringRef Input); + + Reader(const Reader &) = delete; + Reader &operator=(const Reader &) = delete; + + /// Read one object from the input buffer, advancing past it. + /// + /// The \p Obj is updated with the kind of the object read, and the + /// corresponding union member is updated. + /// + /// For the collection objects (Array and Map), only the length is read, and + /// the caller must make and additional \c N calls (in the case of Array) or + /// \c N*2 calls (in the case of Map) to \c Read to retrieve the collection + /// elements. + /// + /// \param [out] Obj filled with next object on success. + /// + /// \returns true when object successfully read, false when at end of + /// input (and so \p Obj was not updated), otherwise an error. + Expected read(Object &Obj); + +private: + MemoryBufferRef InputBuffer; + StringRef::iterator Current; + StringRef::iterator End; + + size_t remainingSpace() { + // The rest of the code maintains the invariant that End >= Current, so + // that this cast is always defined behavior. + return static_cast(End - Current); + } + + template Expected readRaw(Object &Obj); + template Expected readInt(Object &Obj); + template Expected readUInt(Object &Obj); + template Expected readLength(Object &Obj); + template Expected readExt(Object &Obj); + Expected createRaw(Object &Obj, uint32_t Size); + Expected createExt(Object &Obj, uint32_t Size); +}; + +} // end namespace msgpack +} // end namespace llvm + +#endif // LLVM_SUPPORT_MSGPACKREADER_H diff --git a/contrib/llvm/include/llvm/BinaryFormat/MsgPackTypes.h b/contrib/llvm/include/llvm/BinaryFormat/MsgPackTypes.h new file mode 100644 index 00000000000..f96cd4c338f --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/MsgPackTypes.h @@ -0,0 +1,372 @@ +//===- MsgPackTypes.h - MsgPack Types ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This is a data structure for representing MessagePack "documents", with +/// methods to go to and from MessagePack. The types also specialize YAMLIO +/// traits in order to go to and from YAML. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Optional.h" +#include "llvm/BinaryFormat/MsgPackReader.h" +#include "llvm/BinaryFormat/MsgPackWriter.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/YAMLTraits.h" +#include + +#ifndef LLVM_BINARYFORMAT_MSGPACKTYPES_H +#define LLVM_BINARYFORMAT_MSGPACKTYPES_H + +namespace llvm { +namespace msgpack { + +class Node; + +/// Short-hand for a Node pointer. +using NodePtr = std::shared_ptr; + +/// Short-hand for an Optional Node pointer. +using OptNodePtr = Optional; + +/// Abstract base-class which can be any MessagePack type. +class Node { +public: + enum NodeKind { + NK_Scalar, + NK_Array, + NK_Map, + }; + +private: + virtual void anchor() = 0; + const NodeKind Kind; + + static Expected readArray(Reader &MPReader, size_t Length); + static Expected readMap(Reader &MPReader, size_t Length); + +public: + NodeKind getKind() const { return Kind; } + + /// Construct a Node. Used by derived classes to track kind information. + Node(NodeKind Kind) : Kind(Kind) {} + + virtual ~Node() = default; + + /// Read from a MessagePack reader \p MPReader, returning an error if one is + /// encountered, or None if \p MPReader is at the end of stream, or some Node + /// pointer if some type is read. + static Expected read(Reader &MPReader); + + /// Write to a MessagePack writer \p MPWriter. + virtual void write(Writer &MPWriter) = 0; +}; + +/// A MessagePack scalar. +class ScalarNode : public Node { +public: + enum ScalarKind { + SK_Int, + SK_UInt, + SK_Nil, + SK_Boolean, + SK_Float, + SK_String, + SK_Binary, + }; + +private: + void anchor() override; + + void destroy(); + + ScalarKind SKind; + + union { + int64_t IntValue; + uint64_t UIntValue; + bool BoolValue; + double FloatValue; + std::string StringValue; + }; + +public: + /// Construct an Int ScalarNode. + ScalarNode(int64_t IntValue); + /// Construct an Int ScalarNode. + ScalarNode(int32_t IntValue); + /// Construct an UInt ScalarNode. + ScalarNode(uint64_t UIntValue); + /// Construct an UInt ScalarNode. + ScalarNode(uint32_t UIntValue); + /// Construct a Nil ScalarNode. + ScalarNode(); + /// Construct a Boolean ScalarNode. + ScalarNode(bool BoolValue); + /// Construct a Float ScalarNode. + ScalarNode(double FloatValue); + /// Construct a String ScalarNode. + ScalarNode(StringRef StringValue); + /// Construct a String ScalarNode. + ScalarNode(const char *StringValue); + /// Construct a String ScalarNode. + ScalarNode(std::string &&StringValue); + /// Construct a Binary ScalarNode. + ScalarNode(MemoryBufferRef BinaryValue); + + ~ScalarNode(); + + ScalarNode &operator=(const ScalarNode &RHS) = delete; + /// A ScalarNode can only be move assigned. + ScalarNode &operator=(ScalarNode &&RHS); + + /// Change the kind of this ScalarNode, zero initializing it to the new type. + void setScalarKind(ScalarKind SKind) { + switch (SKind) { + case SK_Int: + *this = int64_t(0); + break; + case SK_UInt: + *this = uint64_t(0); + break; + case SK_Boolean: + *this = false; + break; + case SK_Float: + *this = 0.0; + break; + case SK_String: + *this = StringRef(); + break; + case SK_Binary: + *this = MemoryBufferRef("", ""); + break; + case SK_Nil: + *this = ScalarNode(); + break; + } + } + + /// Get the current kind of ScalarNode. + ScalarKind getScalarKind() { return SKind; } + + /// Get the value of an Int scalar. + /// + /// \warning Assumes getScalarKind() == SK_Int + int64_t getInt() { + assert(SKind == SK_Int); + return IntValue; + } + + /// Get the value of a UInt scalar. + /// + /// \warning Assumes getScalarKind() == SK_UInt + uint64_t getUInt() { + assert(SKind == SK_UInt); + return UIntValue; + } + + /// Get the value of an Boolean scalar. + /// + /// \warning Assumes getScalarKind() == SK_Boolean + bool getBool() { + assert(SKind == SK_Boolean); + return BoolValue; + } + + /// Get the value of an Float scalar. + /// + /// \warning Assumes getScalarKind() == SK_Float + double getFloat() { + assert(SKind == SK_Float); + return FloatValue; + } + + /// Get the value of a String scalar. + /// + /// \warning Assumes getScalarKind() == SK_String + StringRef getString() { + assert(SKind == SK_String); + return StringValue; + } + + /// Get the value of a Binary scalar. + /// + /// \warning Assumes getScalarKind() == SK_Binary + StringRef getBinary() { + assert(SKind == SK_Binary); + return StringValue; + } + + static bool classof(const Node *N) { return N->getKind() == NK_Scalar; } + + void write(Writer &MPWriter) override; + + /// Parse a YAML scalar of the current ScalarKind from \p ScalarStr. + /// + /// \returns An empty string on success, otherwise an error message. + StringRef inputYAML(StringRef ScalarStr); + + /// Output a YAML scalar of the current ScalarKind into \p OS. + void outputYAML(raw_ostream &OS) const; + + /// Determine which YAML quoting type the current value would need when + /// output. + yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const; + + /// Get the YAML tag for the current ScalarKind. + StringRef getYAMLTag() const; + + /// Flag which affects how the type handles YAML tags when reading and + /// writing. + /// + /// When false, tags are used when reading and writing. When reading, the tag + /// is used to decide the ScalarKind before parsing. When writing, the tag is + /// output along with the value. + /// + /// When true, tags are ignored when reading and writing. When reading, the + /// ScalarKind is always assumed to be String. When writing, the tag is not + /// output. + bool IgnoreTag = false; + + static const char *IntTag; + static const char *NilTag; + static const char *BooleanTag; + static const char *FloatTag; + static const char *StringTag; + static const char *BinaryTag; +}; + +class ArrayNode : public Node, public std::vector { + void anchor() override; + +public: + ArrayNode() : Node(NK_Array) {} + static bool classof(const Node *N) { return N->getKind() == NK_Array; } + + void write(Writer &MPWriter) override { + MPWriter.writeArraySize(this->size()); + for (auto &N : *this) + N->write(MPWriter); + } +}; + +class MapNode : public Node, public StringMap { + void anchor() override; + +public: + MapNode() : Node(NK_Map) {} + static bool classof(const Node *N) { return N->getKind() == NK_Map; } + + void write(Writer &MPWriter) override { + MPWriter.writeMapSize(this->size()); + for (auto &N : *this) { + MPWriter.write(N.first()); + N.second->write(MPWriter); + } + } +}; + +} // end namespace msgpack + +namespace yaml { + +template <> struct PolymorphicTraits { + static NodeKind getKind(const msgpack::NodePtr &N) { + if (isa(*N)) + return NodeKind::Scalar; + if (isa(*N)) + return NodeKind::Map; + if (isa(*N)) + return NodeKind::Sequence; + llvm_unreachable("NodeKind not supported"); + } + static msgpack::ScalarNode &getAsScalar(msgpack::NodePtr &N) { + if (!N || !isa(*N)) + N.reset(new msgpack::ScalarNode()); + return *cast(N.get()); + } + static msgpack::MapNode &getAsMap(msgpack::NodePtr &N) { + if (!N || !isa(*N)) + N.reset(new msgpack::MapNode()); + return *cast(N.get()); + } + static msgpack::ArrayNode &getAsSequence(msgpack::NodePtr &N) { + if (!N || !isa(*N)) + N.reset(new msgpack::ArrayNode()); + return *cast(N.get()); + } +}; + +template <> struct TaggedScalarTraits { + static void output(const msgpack::ScalarNode &S, void *Ctxt, + raw_ostream &ScalarOS, raw_ostream &TagOS) { + if (!S.IgnoreTag) + TagOS << S.getYAMLTag(); + S.outputYAML(ScalarOS); + } + + static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt, + msgpack::ScalarNode &S) { + if (Tag == msgpack::ScalarNode::IntTag) { + S.setScalarKind(msgpack::ScalarNode::SK_UInt); + if (S.inputYAML(ScalarStr) == StringRef()) + return StringRef(); + S.setScalarKind(msgpack::ScalarNode::SK_Int); + return S.inputYAML(ScalarStr); + } + + if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag || + Tag == "tag:yaml.org,2002:str") + S.setScalarKind(msgpack::ScalarNode::SK_String); + else if (Tag == msgpack::ScalarNode::NilTag) + S.setScalarKind(msgpack::ScalarNode::SK_Nil); + else if (Tag == msgpack::ScalarNode::BooleanTag) + S.setScalarKind(msgpack::ScalarNode::SK_Boolean); + else if (Tag == msgpack::ScalarNode::FloatTag) + S.setScalarKind(msgpack::ScalarNode::SK_Float); + else if (Tag == msgpack::ScalarNode::StringTag) + S.setScalarKind(msgpack::ScalarNode::SK_String); + else if (Tag == msgpack::ScalarNode::BinaryTag) + S.setScalarKind(msgpack::ScalarNode::SK_Binary); + else + return "Unsupported messagepack tag"; + + return S.inputYAML(ScalarStr); + } + + static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str) { + return S.mustQuoteYAML(Str); + } +}; + +template <> struct CustomMappingTraits { + static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M) { + IO.mapRequired(Key.str().c_str(), M[Key]); + } + static void output(IO &IO, msgpack::MapNode &M) { + for (auto &N : M) + IO.mapRequired(N.getKey().str().c_str(), N.getValue()); + } +}; + +template <> struct SequenceTraits { + static size_t size(IO &IO, msgpack::ArrayNode &A) { return A.size(); } + static msgpack::NodePtr &element(IO &IO, msgpack::ArrayNode &A, + size_t Index) { + if (Index >= A.size()) + A.resize(Index + 1); + return A[Index]; + } +}; + +} // end namespace yaml +} // end namespace llvm + +#endif // LLVM_BINARYFORMAT_MSGPACKTYPES_H diff --git a/contrib/llvm/include/llvm/BinaryFormat/MsgPackWriter.h b/contrib/llvm/include/llvm/BinaryFormat/MsgPackWriter.h new file mode 100644 index 00000000000..98af422c9f1 --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/MsgPackWriter.h @@ -0,0 +1,131 @@ +//===- MsgPackWriter.h - Simple MsgPack writer ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains a MessagePack writer. +/// +/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full +/// specification. +/// +/// Typical usage: +/// \code +/// raw_ostream output = GetOutputStream(); +/// msgpack::Writer MPWriter(output); +/// MPWriter.writeNil(); +/// MPWriter.write(false); +/// MPWriter.write("string"); +/// // ... +/// \endcode +/// +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MSGPACKPARSER_H +#define LLVM_SUPPORT_MSGPACKPARSER_H + +#include "llvm/BinaryFormat/MsgPack.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace msgpack { + +/// Writes MessagePack objects to an output stream, one at a time. +class Writer { +public: + /// Construct a writer, optionally enabling "Compatibility Mode" as defined + /// in the MessagePack specification. + /// + /// When in \p Compatible mode, the writer will write \c Str16 formats + /// instead of \c Str8 formats, and will refuse to write any \c Bin formats. + /// + /// \param OS stream to output MessagePack objects to. + /// \param Compatible when set, write in "Compatibility Mode". + Writer(raw_ostream &OS, bool Compatible = false); + + Writer(const Writer &) = delete; + Writer &operator=(const Writer &) = delete; + + /// Write a \em Nil to the output stream. + /// + /// The output will be the \em nil format. + void writeNil(); + + /// Write a \em Boolean to the output stream. + /// + /// The output will be a \em bool format. + void write(bool b); + + /// Write a signed integer to the output stream. + /// + /// The output will be in the smallest possible \em int format. + /// + /// The format chosen may be for an unsigned integer. + void write(int64_t i); + + /// Write an unsigned integer to the output stream. + /// + /// The output will be in the smallest possible \em int format. + void write(uint64_t u); + + /// Write a floating point number to the output stream. + /// + /// The output will be in the smallest possible \em float format. + void write(double d); + + /// Write a string to the output stream. + /// + /// The output will be in the smallest possible \em str format. + void write(StringRef s); + + /// Write a memory buffer to the output stream. + /// + /// The output will be in the smallest possible \em bin format. + /// + /// \warning Do not use this overload if in \c Compatible mode. + void write(MemoryBufferRef Buffer); + + /// Write the header for an \em Array of the given size. + /// + /// The output will be in the smallest possible \em array format. + // + /// The header contains an identifier for the \em array format used, as well + /// as an encoding of the size of the array. + /// + /// N.B. The caller must subsequently call \c Write an additional \p Size + /// times to complete the array. + void writeArraySize(uint32_t Size); + + /// Write the header for a \em Map of the given size. + /// + /// The output will be in the smallest possible \em map format. + // + /// The header contains an identifier for the \em map format used, as well + /// as an encoding of the size of the map. + /// + /// N.B. The caller must subsequently call \c Write and additional \c Size*2 + /// times to complete the map. Each even numbered call to \c Write defines a + /// new key, and each odd numbered call defines the previous key's value. + void writeMapSize(uint32_t Size); + + /// Write a typed memory buffer (an extension type) to the output stream. + /// + /// The output will be in the smallest possible \em ext format. + void writeExt(int8_t Type, MemoryBufferRef Buffer); + +private: + support::endian::Writer EW; + bool Compatible; +}; + +} // end namespace msgpack +} // end namespace llvm + +#endif // LLVM_SUPPORT_MSGPACKPARSER_H diff --git a/contrib/llvm/include/llvm/BinaryFormat/Wasm.h b/contrib/llvm/include/llvm/BinaryFormat/Wasm.h index fa5448dacec..d9f0f94b298 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/contrib/llvm/include/llvm/BinaryFormat/Wasm.h @@ -16,6 +16,7 @@ #define LLVM_BINARYFORMAT_WASM_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" namespace llvm { namespace wasm { @@ -25,7 +26,7 @@ const char WasmMagic[] = {'\0', 'a', 's', 'm'}; // Wasm binary format version const uint32_t WasmVersion = 0x1; // Wasm linking metadata version -const uint32_t WasmMetadataVersion = 0x1; +const uint32_t WasmMetadataVersion = 0x2; // Wasm uses a 64k page size const uint32_t WasmPageSize = 65536; @@ -34,9 +35,12 @@ struct WasmObjectHeader { uint32_t Version; }; -struct WasmSignature { - std::vector ParamTypes; - uint8_t ReturnType; +struct WasmDylinkInfo { + uint32_t MemorySize; // Memory size in bytes + uint32_t MemoryAlignment; // P2 alignment of memory + uint32_t TableSize; // Table size in elements + uint32_t TableAlignment; // P2 alignment of table + std::vector Needed; // Shared library depenedencies }; struct WasmExport { @@ -79,6 +83,18 @@ struct WasmGlobal { StringRef SymbolName; // from the "linking" section }; +struct WasmEventType { + // Kind of event. Currently only WASM_EVENT_ATTRIBUTE_EXCEPTION is possible. + uint32_t Attribute; + uint32_t SigIndex; +}; + +struct WasmEvent { + uint32_t Index; + WasmEventType Type; + StringRef SymbolName; // from the "linking" section +}; + struct WasmImport { StringRef Module; StringRef Field; @@ -88,6 +104,7 @@ struct WasmImport { WasmGlobalType Global; WasmTable Table; WasmLimits Memory; + WasmEventType Event; }; }; @@ -104,8 +121,8 @@ struct WasmFunction { uint32_t Size; uint32_t CodeOffset; // start of Locals and Body StringRef SymbolName; // from the "linking" section - StringRef DebugName; // from the "name" section - uint32_t Comdat; // from the "comdat info" section + StringRef DebugName; // from the "name" section + uint32_t Comdat; // from the "comdat info" section }; struct WasmDataSegment { @@ -171,18 +188,20 @@ struct WasmLinkingData { }; enum : unsigned { - WASM_SEC_CUSTOM = 0, // Custom / User-defined section - WASM_SEC_TYPE = 1, // Function signature declarations - WASM_SEC_IMPORT = 2, // Import declarations - WASM_SEC_FUNCTION = 3, // Function declarations - WASM_SEC_TABLE = 4, // Indirect function table and other tables - WASM_SEC_MEMORY = 5, // Memory attributes - WASM_SEC_GLOBAL = 6, // Global declarations - WASM_SEC_EXPORT = 7, // Exports - WASM_SEC_START = 8, // Start function declaration - WASM_SEC_ELEM = 9, // Elements section - WASM_SEC_CODE = 10, // Function bodies (code) - WASM_SEC_DATA = 11 // Data segments + WASM_SEC_CUSTOM = 0, // Custom / User-defined section + WASM_SEC_TYPE = 1, // Function signature declarations + WASM_SEC_IMPORT = 2, // Import declarations + WASM_SEC_FUNCTION = 3, // Function declarations + WASM_SEC_TABLE = 4, // Indirect function table and other tables + WASM_SEC_MEMORY = 5, // Memory attributes + WASM_SEC_GLOBAL = 6, // Global declarations + WASM_SEC_EXPORT = 7, // Exports + WASM_SEC_START = 8, // Start function declaration + WASM_SEC_ELEM = 9, // Elements section + WASM_SEC_CODE = 10, // Function bodies (code) + WASM_SEC_DATA = 11, // Data segments + WASM_SEC_DATACOUNT = 12, // Data segment count + WASM_SEC_EVENT = 13 // Event declarations }; // Type immediate encodings used in various contexts. @@ -191,7 +210,8 @@ enum : unsigned { WASM_TYPE_I64 = 0x7E, WASM_TYPE_F32 = 0x7D, WASM_TYPE_F64 = 0x7C, - WASM_TYPE_ANYFUNC = 0x70, + WASM_TYPE_V128 = 0x7B, + WASM_TYPE_FUNCREF = 0x70, WASM_TYPE_EXCEPT_REF = 0x68, WASM_TYPE_FUNC = 0x60, WASM_TYPE_NORESULT = 0x40, // for blocks with no result values @@ -203,12 +223,13 @@ enum : unsigned { WASM_EXTERNAL_TABLE = 0x1, WASM_EXTERNAL_MEMORY = 0x2, WASM_EXTERNAL_GLOBAL = 0x3, + WASM_EXTERNAL_EVENT = 0x4, }; // Opcodes used in initializer expressions. enum : unsigned { WASM_OPCODE_END = 0x0b, - WASM_OPCODE_GET_GLOBAL = 0x23, + WASM_OPCODE_GLOBAL_GET = 0x23, WASM_OPCODE_I32_CONST = 0x41, WASM_OPCODE_I64_CONST = 0x42, WASM_OPCODE_F32_CONST = 0x43, @@ -217,35 +238,27 @@ enum : unsigned { enum : unsigned { WASM_LIMITS_FLAG_HAS_MAX = 0x1, -}; - -// Subset of types that a value can have -enum class ValType { - I32 = WASM_TYPE_I32, - I64 = WASM_TYPE_I64, - F32 = WASM_TYPE_F32, - F64 = WASM_TYPE_F64, - EXCEPT_REF = WASM_TYPE_EXCEPT_REF, + WASM_LIMITS_FLAG_IS_SHARED = 0x2, }; // Kind codes used in the custom "name" section enum : unsigned { WASM_NAMES_FUNCTION = 0x1, - WASM_NAMES_LOCAL = 0x2, + WASM_NAMES_LOCAL = 0x2, }; // Kind codes used in the custom "linking" section enum : unsigned { - WASM_SEGMENT_INFO = 0x5, - WASM_INIT_FUNCS = 0x6, - WASM_COMDAT_INFO = 0x7, - WASM_SYMBOL_TABLE = 0x8, + WASM_SEGMENT_INFO = 0x5, + WASM_INIT_FUNCS = 0x6, + WASM_COMDAT_INFO = 0x7, + WASM_SYMBOL_TABLE = 0x8, }; // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO enum : unsigned { - WASM_COMDAT_DATA = 0x0, - WASM_COMDAT_FUNCTION = 0x1, + WASM_COMDAT_DATA = 0x0, + WASM_COMDAT_FUNCTION = 0x1, }; // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE @@ -254,17 +267,23 @@ enum WasmSymbolType : unsigned { WASM_SYMBOL_TYPE_DATA = 0x1, WASM_SYMBOL_TYPE_GLOBAL = 0x2, WASM_SYMBOL_TYPE_SECTION = 0x3, + WASM_SYMBOL_TYPE_EVENT = 0x4, }; -const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; -const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; +// Kinds of event attributes. +enum WasmEventAttribute : unsigned { + WASM_EVENT_ATTRIBUTE_EXCEPTION = 0x0, +}; -const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; -const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; -const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; +const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; +const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; + +const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; +const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; +const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; -const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; -const unsigned WASM_SYMBOL_UNDEFINED = 0x10; +const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; +const unsigned WASM_SYMBOL_UNDEFINED = 0x10; #define WASM_RELOC(name, value) name = value, @@ -274,9 +293,32 @@ enum : unsigned { #undef WASM_RELOC +// Subset of types that a value can have +enum class ValType { + I32 = WASM_TYPE_I32, + I64 = WASM_TYPE_I64, + F32 = WASM_TYPE_F32, + F64 = WASM_TYPE_F64, + V128 = WASM_TYPE_V128, + EXCEPT_REF = WASM_TYPE_EXCEPT_REF, +}; + +struct WasmSignature { + SmallVector Returns; + SmallVector Params; + // Support empty and tombstone instances, needed by DenseMap. + enum { Plain, Empty, Tombstone } State = Plain; + + WasmSignature(SmallVector &&InReturns, + SmallVector &&InParams) + : Returns(InReturns), Params(InParams) {} + WasmSignature() = default; +}; + // Useful comparison operators inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { - return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes; + return LHS.State == RHS.State && LHS.Returns == RHS.Returns && + LHS.Params == RHS.Params; } inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { diff --git a/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def index 8ffd51e483f..b3a08e70c1d 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def +++ b/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def @@ -1,4 +1,3 @@ - #ifndef WASM_RELOC #error "WASM_RELOC must be defined" #endif @@ -13,3 +12,4 @@ WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB, 6) WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7) WASM_RELOC(R_WEBASSEMBLY_FUNCTION_OFFSET_I32, 8) WASM_RELOC(R_WEBASSEMBLY_SECTION_OFFSET_I32, 9) +WASM_RELOC(R_WEBASSEMBLY_EVENT_INDEX_LEB, 10) diff --git a/contrib/llvm/include/llvm/Bitcode/BitcodeReader.h b/contrib/llvm/include/llvm/Bitcode/BitcodeReader.h index ce8bdd9cf0b..0d7cc141f2c 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitcodeReader.h +++ b/contrib/llvm/include/llvm/Bitcode/BitcodeReader.h @@ -51,6 +51,7 @@ class Module; struct BitcodeLTOInfo { bool IsThinLTO; bool HasSummary; + bool EnableSplitLTOUnit; }; /// Represents a module in a bitcode file. diff --git a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 6723cf42dd2..f0d11e9c168 100644 --- a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -342,6 +342,7 @@ enum ConstantsCodes { CST_CODE_INLINEASM = 23, // INLINEASM: [sideeffect|alignstack| // asmdialect,asmstr,conststr] CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] + CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] }; /// CastOpcodes - These are values used in the bitcode files to encode which @@ -364,6 +365,14 @@ enum CastOpcodes { CAST_ADDRSPACECAST = 12 }; +/// UnaryOpcodes - These are values used in the bitcode files to encode which +/// unop a CST_CODE_CE_UNOP or a XXX refers to. The values of these enums +/// have no fixed relation to the LLVM IR enum values. Changing these will +/// break compatibility with old files. +enum UnaryOpcodes { + UNOP_NEG = 0 +}; + /// BinaryOpcodes - These are values used in the bitcode files to encode which /// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums /// have no fixed relation to the LLVM IR enum values. Changing these will @@ -524,6 +533,7 @@ enum FunctionCodes { // 53 is unused. // 54 is unused. FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...] + FUNC_CODE_INST_UNOP = 56, // UNOP: [opcode, ty, opval] }; enum UseListCodes { @@ -591,6 +601,7 @@ enum AttributeKindCodes { ATTR_KIND_NOCF_CHECK = 56, ATTR_KIND_OPT_FOR_FUZZING = 57, ATTR_KIND_SHADOWCALLSTACK = 58, + ATTR_KIND_SPECULATIVE_LOAD_HARDENING = 59, }; enum ComdatSelectionKindCodes { diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h index b6056380916..413901d218f 100644 --- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -71,6 +71,7 @@ class MCTargetOptions; class MDNode; class Module; class raw_ostream; +class StackMaps; class TargetLoweringObjectFile; class TargetMachine; @@ -137,6 +138,9 @@ private: static char ID; +protected: + /// Protected struct HandlerInfo and Handlers permit target extended + /// AsmPrinter adds their own handlers. struct HandlerInfo { AsmPrinterHandler *Handler; const char *TimerName; @@ -365,6 +369,9 @@ public: /// emit the proxies we previously omitted in EmitGlobalVariable. void emitGlobalGOTEquivs(); + /// Emit the stack maps. + void emitStackMaps(StackMaps &SM); + //===------------------------------------------------------------------===// // Overridable Hooks //===------------------------------------------------------------------===// @@ -542,7 +549,7 @@ public: /// /// \p Value - The value to emit. /// \p Size - The size of the integer (in bytes) to emit. - virtual void EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const; + virtual void EmitDebugValue(const MCExpr *Value, unsigned Size) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines @@ -631,6 +638,11 @@ private: /// inline asm. void EmitInlineAsm(const MachineInstr *MI) const; + /// Add inline assembly info to the diagnostics machinery, so we can + /// emit file and position info. Returns SrcMgr memory buffer position. + unsigned addInlineAsmDiagBuffer(StringRef AsmStr, + const MDNode *LocMDNode) const; + //===------------------------------------------------------------------===// // Internal Implementation Details //===------------------------------------------------------------------===// @@ -647,6 +659,8 @@ private: void EmitLLVMUsedList(const ConstantArray *InitList); /// Emit llvm.ident metadata in an '.ident' directive. void EmitModuleIdents(Module &M); + /// Emit bytes for llvm.commandline metadata. + void EmitModuleCommandLines(Module &M); void EmitXXStructorList(const DataLayout &DL, const Constant *List, bool isCtor); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinterHandler.h similarity index 92% rename from contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h rename to contrib/llvm/include/llvm/CodeGen/AsmPrinterHandler.h index f5ac95a20b1..a8b13200dd4 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h +++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinterHandler.h @@ -1,4 +1,4 @@ -//===-- lib/CodeGen/AsmPrinter/AsmPrinterHandler.h -------------*- C++ -*--===// +//===-- llvm/CodeGen/AsmPrinterHandler.h -----------------------*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H -#define LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H +#ifndef LLVM_CODEGEN_ASMPRINTERHANDLER_H +#define LLVM_CODEGEN_ASMPRINTERHANDLER_H #include "llvm/Support/DataTypes.h" diff --git a/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h index f76a2426377..f105d887c39 100644 --- a/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h @@ -80,6 +80,23 @@ private: using BaseT = TargetTransformInfoImplCRTPBase; using TTI = TargetTransformInfo; + /// Estimate a cost of Broadcast as an extract and sequence of insert + /// operations. + unsigned getBroadcastShuffleOverhead(Type *Ty) { + assert(Ty->isVectorTy() && "Can only shuffle vectors"); + unsigned Cost = 0; + // Broadcast cost is equal to the cost of extracting the zero'th element + // plus the cost of inserting it into every element of the result vector. + Cost += static_cast(this)->getVectorInstrCost( + Instruction::ExtractElement, Ty, 0); + + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + Cost += static_cast(this)->getVectorInstrCost( + Instruction::InsertElement, Ty, i); + } + return Cost; + } + /// Estimate a cost of shuffle as a sequence of extract and insert /// operations. unsigned getPermuteShuffleOverhead(Type *Ty) { @@ -101,6 +118,50 @@ private: return Cost; } + /// Estimate a cost of subvector extraction as a sequence of extract and + /// insert operations. + unsigned getExtractSubvectorOverhead(Type *Ty, int Index, Type *SubTy) { + assert(Ty && Ty->isVectorTy() && SubTy && SubTy->isVectorTy() && + "Can only extract subvectors from vectors"); + int NumSubElts = SubTy->getVectorNumElements(); + assert((Index + NumSubElts) <= (int)Ty->getVectorNumElements() && + "SK_ExtractSubvector index out of range"); + + unsigned Cost = 0; + // Subvector extraction cost is equal to the cost of extracting element from + // the source type plus the cost of inserting them into the result vector + // type. + for (int i = 0; i != NumSubElts; ++i) { + Cost += static_cast(this)->getVectorInstrCost( + Instruction::ExtractElement, Ty, i + Index); + Cost += static_cast(this)->getVectorInstrCost( + Instruction::InsertElement, SubTy, i); + } + return Cost; + } + + /// Estimate a cost of subvector insertion as a sequence of extract and + /// insert operations. + unsigned getInsertSubvectorOverhead(Type *Ty, int Index, Type *SubTy) { + assert(Ty && Ty->isVectorTy() && SubTy && SubTy->isVectorTy() && + "Can only insert subvectors into vectors"); + int NumSubElts = SubTy->getVectorNumElements(); + assert((Index + NumSubElts) <= (int)Ty->getVectorNumElements() && + "SK_InsertSubvector index out of range"); + + unsigned Cost = 0; + // Subvector insertion cost is equal to the cost of extracting element from + // the source type plus the cost of inserting them into the result vector + // type. + for (int i = 0; i != NumSubElts; ++i) { + Cost += static_cast(this)->getVectorInstrCost( + Instruction::ExtractElement, SubTy, i); + Cost += static_cast(this)->getVectorInstrCost( + Instruction::InsertElement, Ty, i + Index); + } + return Cost; + } + /// Local query method delegates up to T which *must* implement this! const TargetSubtargetInfo *getST() const { return static_cast(this)->getST(); @@ -554,14 +615,20 @@ public: unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, Type *SubTp) { switch (Kind) { + case TTI::SK_Broadcast: + return getBroadcastShuffleOverhead(Tp); case TTI::SK_Select: + case TTI::SK_Reverse: case TTI::SK_Transpose: case TTI::SK_PermuteSingleSrc: case TTI::SK_PermuteTwoSrc: return getPermuteShuffleOverhead(Tp); - default: - return 1; + case TTI::SK_ExtractSubvector: + return getExtractSubvectorOverhead(Tp, Index, SubTp); + case TTI::SK_InsertSubvector: + return getInsertSubvectorOverhead(Tp, Index, SubTp); } + llvm_unreachable("Unknown TTI::ShuffleKind"); } unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, @@ -783,8 +850,9 @@ public: unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef Indices, - unsigned Alignment, - unsigned AddressSpace) { + unsigned Alignment, unsigned AddressSpace, + bool UseMaskForCond = false, + bool UseMaskForGaps = false) { VectorType *VT = dyn_cast(VecTy); assert(VT && "Expect a vector type for interleaved memory op"); @@ -795,8 +863,13 @@ public: VectorType *SubVT = VectorType::get(VT->getElementType(), NumSubElts); // Firstly, the cost of load/store operation. - unsigned Cost = static_cast(this)->getMemoryOpCost( - Opcode, VecTy, Alignment, AddressSpace); + unsigned Cost; + if (UseMaskForCond || UseMaskForGaps) + Cost = static_cast(this)->getMaskedMemoryOpCost( + Opcode, VecTy, Alignment, AddressSpace); + else + Cost = static_cast(this)->getMemoryOpCost(Opcode, VecTy, Alignment, + AddressSpace); // Legalize the vector type, and get the legalized and unlegalized type // sizes. @@ -892,6 +965,40 @@ public: ->getVectorInstrCost(Instruction::InsertElement, VT, i); } + if (!UseMaskForCond) + return Cost; + + Type *I8Type = Type::getInt8Ty(VT->getContext()); + VectorType *MaskVT = VectorType::get(I8Type, NumElts); + SubVT = VectorType::get(I8Type, NumSubElts); + + // The Mask shuffling cost is extract all the elements of the Mask + // and insert each of them Factor times into the wide vector: + // + // E.g. an interleaved group with factor 3: + // %mask = icmp ult <8 x i32> %vec1, %vec2 + // %interleaved.mask = shufflevector <8 x i1> %mask, <8 x i1> undef, + // <24 x i32> <0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7> + // The cost is estimated as extract all mask elements from the <8xi1> mask + // vector and insert them factor times into the <24xi1> shuffled mask + // vector. + for (unsigned i = 0; i < NumSubElts; i++) + Cost += static_cast(this)->getVectorInstrCost( + Instruction::ExtractElement, SubVT, i); + + for (unsigned i = 0; i < NumElts; i++) + Cost += static_cast(this)->getVectorInstrCost( + Instruction::InsertElement, MaskVT, i); + + // The Gaps mask is invariant and created outside the loop, therefore the + // cost of creating it is not accounted for here. However if we have both + // a MaskForGaps and some other mask that guards the execution of the + // memory access, we need to account for the cost of And-ing the two masks + // inside the loop. + if (UseMaskForGaps) + Cost += static_cast(this)->getArithmeticInstrCost( + BinaryOperator::And, MaskVT); + return Cost; } @@ -901,6 +1008,7 @@ public: unsigned VF = 1) { unsigned RetVF = (RetTy->isVectorTy() ? RetTy->getVectorNumElements() : 1); assert((RetVF == 1 || VF == 1) && "VF > 1 and RetVF is a vector type"); + auto *ConcreteTTI = static_cast(this); switch (IID) { default: { @@ -926,29 +1034,24 @@ public: ScalarizationCost += getOperandsScalarizationOverhead(Args, VF); } - return static_cast(this)-> - getIntrinsicInstrCost(IID, RetTy, Types, FMF, ScalarizationCost); + return ConcreteTTI->getIntrinsicInstrCost(IID, RetTy, Types, FMF, + ScalarizationCost); } case Intrinsic::masked_scatter: { assert(VF == 1 && "Can't vectorize types here."); Value *Mask = Args[3]; bool VarMask = !isa(Mask); unsigned Alignment = cast(Args[2])->getZExtValue(); - return - static_cast(this)->getGatherScatterOpCost(Instruction::Store, - Args[0]->getType(), - Args[1], VarMask, - Alignment); + return ConcreteTTI->getGatherScatterOpCost( + Instruction::Store, Args[0]->getType(), Args[1], VarMask, Alignment); } case Intrinsic::masked_gather: { assert(VF == 1 && "Can't vectorize types here."); Value *Mask = Args[2]; bool VarMask = !isa(Mask); unsigned Alignment = cast(Args[1])->getZExtValue(); - return - static_cast(this)->getGatherScatterOpCost(Instruction::Load, - RetTy, Args[0], VarMask, - Alignment); + return ConcreteTTI->getGatherScatterOpCost(Instruction::Load, RetTy, + Args[0], VarMask, Alignment); } case Intrinsic::experimental_vector_reduce_add: case Intrinsic::experimental_vector_reduce_mul: @@ -964,6 +1067,45 @@ public: case Intrinsic::experimental_vector_reduce_umax: case Intrinsic::experimental_vector_reduce_umin: return getIntrinsicInstrCost(IID, RetTy, Args[0]->getType(), FMF); + case Intrinsic::fshl: + case Intrinsic::fshr: { + Value *X = Args[0]; + Value *Y = Args[1]; + Value *Z = Args[2]; + TTI::OperandValueProperties OpPropsX, OpPropsY, OpPropsZ, OpPropsBW; + TTI::OperandValueKind OpKindX = TTI::getOperandInfo(X, OpPropsX); + TTI::OperandValueKind OpKindY = TTI::getOperandInfo(Y, OpPropsY); + TTI::OperandValueKind OpKindZ = TTI::getOperandInfo(Z, OpPropsZ); + TTI::OperandValueKind OpKindBW = TTI::OK_UniformConstantValue; + OpPropsBW = isPowerOf2_32(RetTy->getScalarSizeInBits()) ? TTI::OP_PowerOf2 + : TTI::OP_None; + // fshl: (X << (Z % BW)) | (Y >> (BW - (Z % BW))) + // fshr: (X << (BW - (Z % BW))) | (Y >> (Z % BW)) + unsigned Cost = 0; + Cost += ConcreteTTI->getArithmeticInstrCost(BinaryOperator::Or, RetTy); + Cost += ConcreteTTI->getArithmeticInstrCost(BinaryOperator::Sub, RetTy); + Cost += ConcreteTTI->getArithmeticInstrCost(BinaryOperator::Shl, RetTy, + OpKindX, OpKindZ, OpPropsX); + Cost += ConcreteTTI->getArithmeticInstrCost(BinaryOperator::LShr, RetTy, + OpKindY, OpKindZ, OpPropsY); + // Non-constant shift amounts requires a modulo. + if (OpKindZ != TTI::OK_UniformConstantValue && + OpKindZ != TTI::OK_NonUniformConstantValue) + Cost += ConcreteTTI->getArithmeticInstrCost(BinaryOperator::URem, RetTy, + OpKindZ, OpKindBW, OpPropsZ, + OpPropsBW); + // For non-rotates (X != Y) we must add shift-by-zero handling costs. + if (X != Y) { + Type *CondTy = Type::getInt1Ty(RetTy->getContext()); + if (RetVF > 1) + CondTy = VectorType::get(CondTy, RetVF); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, + CondTy, nullptr); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::Select, RetTy, + CondTy, nullptr); + } + return Cost; + } } } @@ -1036,15 +1178,18 @@ public: case Intrinsic::fabs: ISDs.push_back(ISD::FABS); break; + case Intrinsic::canonicalize: + ISDs.push_back(ISD::FCANONICALIZE); + break; case Intrinsic::minnum: ISDs.push_back(ISD::FMINNUM); if (FMF.noNaNs()) - ISDs.push_back(ISD::FMINNAN); + ISDs.push_back(ISD::FMINIMUM); break; case Intrinsic::maxnum: ISDs.push_back(ISD::FMAXNUM); if (FMF.noNaNs()) - ISDs.push_back(ISD::FMAXNAN); + ISDs.push_back(ISD::FMAXIMUM); break; case Intrinsic::copysign: ISDs.push_back(ISD::FCOPYSIGN); @@ -1136,7 +1281,8 @@ public: SmallVector CustomCost; for (unsigned ISD : ISDs) { if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { - if (IID == Intrinsic::fabs && TLI->isFAbsFree(LT.second)) { + if (IID == Intrinsic::fabs && LT.second.isFloatingPoint() && + TLI->isFAbsFree(LT.second)) { return 0; } @@ -1280,24 +1426,36 @@ public: LT.second.isVector() ? LT.second.getVectorNumElements() : 1; while (NumVecElts > MVTLen) { NumVecElts /= 2; + Type *SubTy = VectorType::get(ScalarTy, NumVecElts); // Assume the pairwise shuffles add a cost. ShuffleCost += (IsPairwise + 1) * ConcreteTTI->getShuffleCost(TTI::SK_ExtractSubvector, Ty, - NumVecElts, Ty); - ArithCost += ConcreteTTI->getArithmeticInstrCost(Opcode, Ty); - Ty = VectorType::get(ScalarTy, NumVecElts); + NumVecElts, SubTy); + ArithCost += ConcreteTTI->getArithmeticInstrCost(Opcode, SubTy); + Ty = SubTy; ++LongVectorCount; } + + NumReduxLevels -= LongVectorCount; + // The minimal length of the vector is limited by the real length of vector // operations performed on the current platform. That's why several final // reduction operations are performed on the vectors with the same // architecture-dependent length. - ShuffleCost += (NumReduxLevels - LongVectorCount) * (IsPairwise + 1) * - ConcreteTTI->getShuffleCost(TTI::SK_ExtractSubvector, Ty, - NumVecElts, Ty); - ArithCost += (NumReduxLevels - LongVectorCount) * + + // Non pairwise reductions need one shuffle per reduction level. Pairwise + // reductions need two shuffles on every level, but the last one. On that + // level one of the shuffles is <0, u, u, ...> which is identity. + unsigned NumShuffles = NumReduxLevels; + if (IsPairwise && NumReduxLevels >= 1) + NumShuffles += NumReduxLevels - 1; + ShuffleCost += NumShuffles * + ConcreteTTI->getShuffleCost(TTI::SK_PermuteSingleSrc, Ty, + 0, Ty); + ArithCost += NumReduxLevels * ConcreteTTI->getArithmeticInstrCost(Opcode, Ty); - return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true); + return ShuffleCost + ArithCost + + ConcreteTTI->getVectorInstrCost(Instruction::ExtractElement, Ty, 0); } /// Try to calculate op costs for min/max reduction operations. @@ -1327,37 +1485,46 @@ public: LT.second.isVector() ? LT.second.getVectorNumElements() : 1; while (NumVecElts > MVTLen) { NumVecElts /= 2; + Type *SubTy = VectorType::get(ScalarTy, NumVecElts); + CondTy = VectorType::get(ScalarCondTy, NumVecElts); + // Assume the pairwise shuffles add a cost. ShuffleCost += (IsPairwise + 1) * ConcreteTTI->getShuffleCost(TTI::SK_ExtractSubvector, Ty, - NumVecElts, Ty); + NumVecElts, SubTy); MinMaxCost += - ConcreteTTI->getCmpSelInstrCost(CmpOpcode, Ty, CondTy, nullptr) + - ConcreteTTI->getCmpSelInstrCost(Instruction::Select, Ty, CondTy, + ConcreteTTI->getCmpSelInstrCost(CmpOpcode, SubTy, CondTy, nullptr) + + ConcreteTTI->getCmpSelInstrCost(Instruction::Select, SubTy, CondTy, nullptr); - Ty = VectorType::get(ScalarTy, NumVecElts); - CondTy = VectorType::get(ScalarCondTy, NumVecElts); + Ty = SubTy; ++LongVectorCount; } + + NumReduxLevels -= LongVectorCount; + // The minimal length of the vector is limited by the real length of vector // operations performed on the current platform. That's why several final // reduction opertions are perfomed on the vectors with the same // architecture-dependent length. - ShuffleCost += (NumReduxLevels - LongVectorCount) * (IsPairwise + 1) * - ConcreteTTI->getShuffleCost(TTI::SK_ExtractSubvector, Ty, - NumVecElts, Ty); + + // Non pairwise reductions need one shuffle per reduction level. Pairwise + // reductions need two shuffles on every level, but the last one. On that + // level one of the shuffles is <0, u, u, ...> which is identity. + unsigned NumShuffles = NumReduxLevels; + if (IsPairwise && NumReduxLevels >= 1) + NumShuffles += NumReduxLevels - 1; + ShuffleCost += NumShuffles * + ConcreteTTI->getShuffleCost(TTI::SK_PermuteSingleSrc, Ty, + 0, Ty); MinMaxCost += - (NumReduxLevels - LongVectorCount) * + NumReduxLevels * (ConcreteTTI->getCmpSelInstrCost(CmpOpcode, Ty, CondTy, nullptr) + ConcreteTTI->getCmpSelInstrCost(Instruction::Select, Ty, CondTy, nullptr)); - // Need 3 extractelement instructions for scalarization + an additional - // scalar select instruction. + // The last min/max should be in vector registers and we counted it above. + // So just need a single extractelement. return ShuffleCost + MinMaxCost + - 3 * getScalarizationOverhead(Ty, /*Insert=*/false, - /*Extract=*/true) + - ConcreteTTI->getCmpSelInstrCost(Instruction::Select, ScalarTy, - ScalarCondTy, nullptr); + ConcreteTTI->getVectorInstrCost(Instruction::ExtractElement, Ty, 0); } unsigned getVectorSplitCost() { return 1; } diff --git a/contrib/llvm/include/llvm/CodeGen/GCs.h b/contrib/llvm/include/llvm/CodeGen/BuiltinGCs.h similarity index 56% rename from contrib/llvm/include/llvm/CodeGen/GCs.h rename to contrib/llvm/include/llvm/CodeGen/BuiltinGCs.h index 5207f801c84..1767922fb5a 100644 --- a/contrib/llvm/include/llvm/CodeGen/GCs.h +++ b/contrib/llvm/include/llvm/CodeGen/BuiltinGCs.h @@ -1,4 +1,4 @@ -//===-- GCs.h - Garbage collector linkage hacks ---------------------------===// +//===-- BuiltinGCs.h - Garbage collector linkage hacks --------------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file contains hack functions to force linking in the GC components. +// This file contains hack functions to force linking in the builtin GC +// components. // //===----------------------------------------------------------------------===// @@ -15,32 +16,18 @@ #define LLVM_CODEGEN_GCS_H namespace llvm { -class GCStrategy; -class GCMetadataPrinter; /// FIXME: Collector instances are not useful on their own. These no longer /// serve any purpose except to link in the plugins. -/// Creates a CoreCLR-compatible garbage collector. -void linkCoreCLRGC(); - -/// Creates an ocaml-compatible garbage collector. -void linkOcamlGC(); +/// Ensure the definition of the builtin GCs gets linked in +void linkAllBuiltinGCs(); /// Creates an ocaml-compatible metadata printer. void linkOcamlGCPrinter(); -/// Creates an erlang-compatible garbage collector. -void linkErlangGC(); - /// Creates an erlang-compatible metadata printer. void linkErlangGCPrinter(); - -/// Creates a shadow stack garbage collector. This collector requires no code -/// generator support. -void linkShadowStackGC(); - -void linkStatepointExampleGC(); } #endif diff --git a/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc b/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc index 7d2d167289e..568d329a5e8 100644 --- a/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc +++ b/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc @@ -74,7 +74,8 @@ static cl::opt TMModel( static cl::opt CMModel( "code-model", cl::desc("Choose code model"), - cl::values(clEnumValN(CodeModel::Small, "small", "Small code model"), + cl::values(clEnumValN(CodeModel::Tiny, "tiny", "Tiny 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"))); @@ -113,10 +114,16 @@ static cl::opt FileType( clEnumValN(TargetMachine::CGFT_Null, "null", "Emit nothing, for performance testing"))); -static cl::opt - DisableFPElim("disable-fp-elim", - cl::desc("Disable frame pointer elimination optimization"), - cl::init(false)); +static cl::opt FramePointerUsage( + "frame-pointer", cl::desc("Specify frame pointer elimination optimization"), + cl::init(llvm::FramePointer::None), + cl::values( + clEnumValN(llvm::FramePointer::All, "all", + "Disable frame pointer elimination"), + clEnumValN(llvm::FramePointer::NonLeaf, "non-leaf", + "Disable frame pointer elimination for non-leaf frame"), + clEnumValN(llvm::FramePointer::None, "none", + "Enable frame pointer elimination"))); static cl::opt EnableUnsafeFPMath( "enable-unsafe-fp-math", @@ -367,9 +374,14 @@ setFunctionAttributes(StringRef CPU, StringRef Features, Module &M) { NewAttrs.addAttribute("target-cpu", CPU); if (!Features.empty()) NewAttrs.addAttribute("target-features", Features); - if (DisableFPElim.getNumOccurrences() > 0) - NewAttrs.addAttribute("no-frame-pointer-elim", - DisableFPElim ? "true" : "false"); + if (FramePointerUsage.getNumOccurrences() > 0) { + if (FramePointerUsage == llvm::FramePointer::All) + NewAttrs.addAttribute("frame-pointer", "all"); + else if (FramePointerUsage == llvm::FramePointer::NonLeaf) + NewAttrs.addAttribute("frame-pointer", "non-leaf"); + else if (FramePointerUsage == llvm::FramePointer::None) + NewAttrs.addAttribute("frame-pointer", "none"); + } if (DisableTailCalls.getNumOccurrences() > 0) NewAttrs.addAttribute("disable-tail-calls", toStringRef(DisableTailCalls)); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/contrib/llvm/include/llvm/CodeGen/DbgEntityHistoryCalculator.h similarity index 53% rename from contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h rename to contrib/llvm/include/llvm/CodeGen/DbgEntityHistoryCalculator.h index a262cb38b17..befc28f084e 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h +++ b/contrib/llvm/include/llvm/CodeGen/DbgEntityHistoryCalculator.h @@ -1,4 +1,4 @@ -//===- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h ------*- C++ -*-===// +//===- llvm/CodeGen/DbgEntityHistoryCalculator.h ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H -#define LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H +#ifndef LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H +#define LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" @@ -33,20 +33,19 @@ class DbgValueHistoryMap { public: using InstrRange = std::pair; using InstrRanges = SmallVector; - using InlinedVariable = - std::pair; - using InstrRangesMap = MapVector; + using InlinedEntity = std::pair; + using InstrRangesMap = MapVector; private: InstrRangesMap VarInstrRanges; public: - void startInstrRange(InlinedVariable Var, const MachineInstr &MI); - void endInstrRange(InlinedVariable Var, const MachineInstr &MI); + void startInstrRange(InlinedEntity Var, const MachineInstr &MI); + void endInstrRange(InlinedEntity Var, const MachineInstr &MI); // Returns register currently describing @Var. If @Var is currently // unaccessible or is not described by a register, returns 0. - unsigned getRegisterForVar(InlinedVariable Var) const; + unsigned getRegisterForVar(InlinedEntity Var) const; bool empty() const { return VarInstrRanges.empty(); } void clear() { VarInstrRanges.clear(); } @@ -58,10 +57,31 @@ public: #endif }; -void calculateDbgValueHistory(const MachineFunction *MF, - const TargetRegisterInfo *TRI, - DbgValueHistoryMap &Result); +/// For each inlined instance of a source-level label, keep the corresponding +/// DBG_LABEL instruction. The DBG_LABEL instruction could be used to generate +/// a temporary (assembler) label before it. +class DbgLabelInstrMap { +public: + using InlinedEntity = std::pair; + using InstrMap = MapVector; + +private: + InstrMap LabelInstr; + +public: + void addInstr(InlinedEntity Label, const MachineInstr &MI); + + bool empty() const { return LabelInstr.empty(); } + void clear() { LabelInstr.clear(); } + InstrMap::const_iterator begin() const { return LabelInstr.begin(); } + InstrMap::const_iterator end() const { return LabelInstr.end(); } +}; + +void calculateDbgEntityHistory(const MachineFunction *MF, + const TargetRegisterInfo *TRI, + DbgValueHistoryMap &DbgValues, + DbgLabelInstrMap &DbgLabels); } // end namespace llvm -#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H +#endif // LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h b/contrib/llvm/include/llvm/CodeGen/DebugHandlerBase.h similarity index 88% rename from contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h rename to contrib/llvm/include/llvm/CodeGen/DebugHandlerBase.h index 1ccefe32be7..4f0d14d317f 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h +++ b/contrib/llvm/include/llvm/CodeGen/DebugHandlerBase.h @@ -1,4 +1,4 @@ -//===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h --------*- C++ -*--===// +//===-- llvm/CodeGen/DebugHandlerBase.h -----------------------*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H -#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H +#ifndef LLVM_CODEGEN_DEBUGHANDLERBASE_H +#define LLVM_CODEGEN_DEBUGHANDLERBASE_H -#include "AsmPrinterHandler.h" -#include "DbgValueHistoryCalculator.h" #include "llvm/ADT/Optional.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/CodeGen/LexicalScopes.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -82,6 +82,9 @@ protected: /// variable. Variables are listed in order of appearance. DbgValueHistoryMap DbgValues; + /// Mapping of inlined labels and DBG_LABEL machine instruction. + DbgLabelInstrMap DbgLabels; + /// Maps instruction with label emitted before instruction. /// FIXME: Make this private from DwarfDebug, we have the necessary accessors /// for it. @@ -122,6 +125,10 @@ public: /// Return Label immediately following the instruction. MCSymbol *getLabelAfterInsn(const MachineInstr *MI); + /// Return the function-local offset of an instruction. A label for the + /// instruction \p MI should exist (\ref getLabelAfterInsn). + const MCExpr *getFunctionLocalOffsetAfterInsn(const MachineInstr *MI); + /// If this type is derived from a base type then return base type size. static uint64_t getBaseTypeSize(const DITypeRef TyRef); }; diff --git a/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h b/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h index e6c0483cfc3..8b1a7af17bb 100644 --- a/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h +++ b/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -10,6 +10,7 @@ #ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H #define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/StringMap.h" namespace llvm { @@ -18,34 +19,52 @@ class MCSymbol; /// Data for a string pool entry. struct DwarfStringPoolEntry { + static constexpr unsigned NotIndexed = -1; + MCSymbol *Symbol; unsigned Offset; unsigned Index; + + bool isIndexed() const { return Index != NotIndexed; } }; /// String pool entry reference. -struct DwarfStringPoolEntryRef { - const StringMapEntry *I = nullptr; +class DwarfStringPoolEntryRef { + PointerIntPair *, 1, bool> + MapEntryAndIndexed; + + const StringMapEntry *getMapEntry() const { + return MapEntryAndIndexed.getPointer(); + } public: DwarfStringPoolEntryRef() = default; - explicit DwarfStringPoolEntryRef( - const StringMapEntry &I) - : I(&I) {} + DwarfStringPoolEntryRef(const StringMapEntry &Entry, + bool Indexed) + : MapEntryAndIndexed(&Entry, Indexed) {} - explicit operator bool() const { return I; } + explicit operator bool() const { return getMapEntry(); } MCSymbol *getSymbol() const { - assert(I->second.Symbol && "No symbol available!"); - return I->second.Symbol; + assert(getMapEntry()->second.Symbol && "No symbol available!"); + return getMapEntry()->second.Symbol; } - unsigned getOffset() const { return I->second.Offset; } - unsigned getIndex() const { return I->second.Index; } - StringRef getString() const { return I->first(); } + unsigned getOffset() const { return getMapEntry()->second.Offset; } + bool isIndexed() const { return MapEntryAndIndexed.getInt(); } + unsigned getIndex() const { + assert(isIndexed()); + assert(getMapEntry()->getValue().isIndexed()); + return getMapEntry()->second.Index; + } + StringRef getString() const { return getMapEntry()->first(); } /// Return the entire string pool entry for convenience. - DwarfStringPoolEntry getEntry() const { return I->getValue(); } + DwarfStringPoolEntry getEntry() const { return getMapEntry()->getValue(); } - bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; } - bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; } + bool operator==(const DwarfStringPoolEntryRef &X) const { + return getMapEntry() == X.getMapEntry(); + } + bool operator!=(const DwarfStringPoolEntryRef &X) const { + return getMapEntry() != X.getMapEntry(); + } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index 2da00b7d61a..7c658515de0 100644 --- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -1,4 +1,4 @@ -//===- FunctionLoweringInfo.h - Lower functions from LLVM IR to CodeGen ---===// +//===- FunctionLoweringInfo.h - Lower functions from LLVM IR ---*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -246,6 +246,7 @@ public: return 0; unsigned &R = ValueMap[V]; assert(R == 0 && "Already initialized this value register!"); + assert(VirtReg2Value.empty()); return R = CreateRegs(V->getType()); } diff --git a/contrib/llvm/include/llvm/CodeGen/GCMetadata.h b/contrib/llvm/include/llvm/CodeGen/GCMetadata.h index ad2599fc120..7fb27202c12 100644 --- a/contrib/llvm/include/llvm/CodeGen/GCMetadata.h +++ b/contrib/llvm/include/llvm/CodeGen/GCMetadata.h @@ -55,12 +55,11 @@ class MCSymbol; /// GCPoint - Metadata for a collector-safe point in machine code. /// struct GCPoint { - GC::PointKind Kind; ///< The kind of the safe point. MCSymbol *Label; ///< A label. DebugLoc Loc; - GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) - : Kind(K), Label(L), Loc(std::move(DL)) {} + GCPoint(MCSymbol *L, DebugLoc DL) + : Label(L), Loc(std::move(DL)) {} }; /// GCRoot - Metadata for a pointer to an object managed by the garbage @@ -124,8 +123,8 @@ public: /// addSafePoint - Notes the existence of a safe point. Num is the ID of the /// label just prior to the safe point (if the code generator is using /// MachineModuleInfo). - void addSafePoint(GC::PointKind Kind, MCSymbol *Label, const DebugLoc &DL) { - SafePoints.emplace_back(Kind, Label, DL); + void addSafePoint(MCSymbol *Label, const DebugLoc &DL) { + SafePoints.emplace_back(Label, DL); } /// getFrameSize/setFrameSize - Records the function's frame size. diff --git a/contrib/llvm/include/llvm/CodeGen/GCMetadataPrinter.h b/contrib/llvm/include/llvm/CodeGen/GCMetadataPrinter.h index 1cc69a7b71a..5f1efb2ce02 100644 --- a/contrib/llvm/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/GCMetadataPrinter.h @@ -29,6 +29,7 @@ class GCMetadataPrinter; class GCModuleInfo; class GCStrategy; class Module; +class StackMaps; /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the /// defaults from Registry. @@ -60,6 +61,11 @@ public: /// Called after the assembly for the module is generated by /// the AsmPrinter (but before target specific hooks) virtual void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + + /// Called when the stack maps are generated. Return true if + /// stack maps with a custom format are generated. Otherwise + /// returns false and the default format will be used. + virtual bool emitStackMaps(StackMaps &SM, AsmPrinter &AP) { return false; } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/GCStrategy.h b/contrib/llvm/include/llvm/CodeGen/GCStrategy.h index f835bacfb54..5a60cd7cb82 100644 --- a/contrib/llvm/include/llvm/CodeGen/GCStrategy.h +++ b/contrib/llvm/include/llvm/CodeGen/GCStrategy.h @@ -59,19 +59,6 @@ namespace llvm { class Type; -namespace GC { - -/// PointKind - Used to indicate whether the address of the call instruction -/// or the address after the call instruction is listed in the stackmap. For -/// most runtimes, PostCall safepoints are appropriate. -/// -enum PointKind { - PreCall, ///< Instr is a call instruction. - PostCall ///< Instr is the return address of a call. -}; - -} // end namespace GC - /// GCStrategy describes a garbage collector algorithm's code generation /// requirements, and provides overridable hooks for those needs which cannot /// be abstractly described. GCStrategy objects must be looked up through @@ -88,11 +75,7 @@ protected: /// if set, none of the other options can be /// anything but their default values. - unsigned NeededSafePoints = 0; ///< Bitmask of required safe points. - bool CustomReadBarriers = false; ///< Default is to insert loads. - bool CustomWriteBarriers = false; ///< Default is to insert stores. - bool CustomRoots = false; ///< Default is to pass through to backend. - bool InitRoots= true; ///< If set, roots are nulled during lowering. + bool NeededSafePoints = false; ///< if set, calls are inferred to be safepoints bool UsesMetadata = false; ///< If set, backend must emit metadata tables. public: @@ -103,16 +86,6 @@ public: /// name string specified on functions which use this strategy. const std::string &getName() const { return Name; } - /// By default, write barriers are replaced with simple store - /// instructions. If true, you must provide a custom pass to lower - /// calls to \@llvm.gcwrite. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// By default, read barriers are replaced with simple load - /// instructions. If true, you must provide a custom pass to lower - /// calls to \@llvm.gcread. - bool customReadBarrier() const { return CustomReadBarriers; } - /// Returns true if this strategy is expecting the use of gc.statepoints, /// and false otherwise. bool useStatepoints() const { return UseStatepoints; } @@ -135,25 +108,8 @@ public: */ ///@{ - /// True if safe points of any kind are required. By default, none are - /// recorded. - bool needsSafePoints() const { return NeededSafePoints != 0; } - - /// True if the given kind of safe point is required. By default, none are - /// recorded. - bool needsSafePoint(GC::PointKind Kind) const { - return (NeededSafePoints & 1 << Kind) != 0; - } - - /// By default, roots are left for the code generator so it can generate a - /// stack map. If true, you must provide a custom pass to lower - /// calls to \@llvm.gcroot. - bool customRoots() const { return CustomRoots; } - - /// If set, gcroot intrinsics should initialize their allocas to null - /// before the first use. This is necessary for most GCs and is enabled by - /// default. - bool initializeRoots() const { return InitRoots; } + /// True if safe points need to be inferred on call sites + bool needsSafePoints() const { return NeededSafePoints; } /// If set, appropriate metadata tables must be emitted by the back-end /// (assembler, JIT, or otherwise). For statepoint, this method is diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h new file mode 100644 index 00000000000..ce2d285a99e --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CSEInfo.h @@ -0,0 +1,237 @@ +//===- llvm/CodeGen/GlobalISel/CSEInfo.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// Provides analysis for continuously CSEing during GISel passes. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CODEGEN_GLOBALISEL_CSEINFO_H +#define LLVM_CODEGEN_GLOBALISEL_CSEINFO_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" +#include "llvm/CodeGen/GlobalISel/GISelWorkList.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +/// A class that wraps MachineInstrs and derives from FoldingSetNode in order to +/// be uniqued in a CSEMap. The tradeoff here is extra memory allocations for +/// UniqueMachineInstr vs making MachineInstr bigger. +class UniqueMachineInstr : public FoldingSetNode { + friend class GISelCSEInfo; + const MachineInstr *MI; + explicit UniqueMachineInstr(const MachineInstr *MI) : MI(MI) {} + +public: + void Profile(FoldingSetNodeID &ID); +}; + +// Class representing some configuration that can be done during CSE analysis. +// Currently it only supports shouldCSE method that each pass can set. +class CSEConfig { +public: + virtual ~CSEConfig() = default; + // Hook for defining which Generic instructions should be CSEd. + // GISelCSEInfo currently only calls this hook when dealing with generic + // opcodes. + virtual bool shouldCSEOpc(unsigned Opc); +}; + +// TODO: Find a better place for this. +// Commonly used for O0 config. +class CSEConfigConstantOnly : public CSEConfig { +public: + virtual ~CSEConfigConstantOnly() = default; + virtual bool shouldCSEOpc(unsigned Opc) override; +}; + +/// The CSE Analysis object. +/// This installs itself as a delegate to the MachineFunction to track +/// new instructions as well as deletions. It however will not be able to +/// track instruction mutations. In such cases, recordNewInstruction should be +/// called (for eg inside MachineIRBuilder::recordInsertion). +/// Also because of how just the instruction can be inserted without adding any +/// operands to the instruction, instructions are uniqued and inserted lazily. +/// CSEInfo should assert when trying to enter an incomplete instruction into +/// the CSEMap. There is Opcode level granularity on which instructions can be +/// CSE'd and for now, only Generic instructions are CSEable. +class GISelCSEInfo : public GISelChangeObserver { + // Make it accessible only to CSEMIRBuilder. + friend class CSEMIRBuilder; + + BumpPtrAllocator UniqueInstrAllocator; + FoldingSet CSEMap; + MachineRegisterInfo *MRI = nullptr; + MachineFunction *MF = nullptr; + std::unique_ptr CSEOpt; + /// Keep a cache of UniqueInstrs for each MachineInstr. In GISel, + /// often instructions are mutated (while their ID has completely changed). + /// Whenever mutation happens, invalidate the UniqueMachineInstr for the + /// MachineInstr + DenseMap InstrMapping; + + /// Store instructions that are not fully formed in TemporaryInsts. + /// Also because CSE insertion happens lazily, we can remove insts from this + /// list and avoid inserting and then removing from the CSEMap. + GISelWorkList<8> TemporaryInsts; + + // Only used in asserts. + DenseMap OpcodeHitTable; + + bool isUniqueMachineInstValid(const UniqueMachineInstr &UMI) const; + + void invalidateUniqueMachineInstr(UniqueMachineInstr *UMI); + + UniqueMachineInstr *getNodeIfExists(FoldingSetNodeID &ID, + MachineBasicBlock *MBB, void *&InsertPos); + + /// Allocate and construct a new UniqueMachineInstr for MI and return. + UniqueMachineInstr *getUniqueInstrForMI(const MachineInstr *MI); + + void insertNode(UniqueMachineInstr *UMI, void *InsertPos = nullptr); + + /// Get the MachineInstr(Unique) if it exists already in the CSEMap and the + /// same MachineBasicBlock. + MachineInstr *getMachineInstrIfExists(FoldingSetNodeID &ID, + MachineBasicBlock *MBB, + void *&InsertPos); + + /// Use this method to allocate a new UniqueMachineInstr for MI and insert it + /// into the CSEMap. MI should return true for shouldCSE(MI->getOpcode()) + void insertInstr(MachineInstr *MI, void *InsertPos = nullptr); + +public: + GISelCSEInfo() = default; + + virtual ~GISelCSEInfo(); + + void setMF(MachineFunction &MF); + + /// Records a newly created inst in a list and lazily insert it to the CSEMap. + /// Sometimes, this method might be called with a partially constructed + /// MachineInstr, + // (right after BuildMI without adding any operands) - and in such cases, + // defer the hashing of the instruction to a later stage. + void recordNewInstruction(MachineInstr *MI); + + /// Use this callback to inform CSE about a newly fully created instruction. + void handleRecordedInst(MachineInstr *MI); + + /// Use this callback to insert all the recorded instructions. At this point, + /// all of these insts need to be fully constructed and should not be missing + /// any operands. + void handleRecordedInsts(); + + /// Remove this inst from the CSE map. If this inst has not been inserted yet, + /// it will be removed from the Tempinsts list if it exists. + void handleRemoveInst(MachineInstr *MI); + + void releaseMemory(); + + void setCSEConfig(std::unique_ptr Opt) { CSEOpt = std::move(Opt); } + + bool shouldCSE(unsigned Opc) const; + + void analyze(MachineFunction &MF); + + void countOpcodeHit(unsigned Opc); + + void print(); + + // Observer API + void erasingInstr(MachineInstr &MI) override; + void createdInstr(MachineInstr &MI) override; + void changingInstr(MachineInstr &MI) override; + void changedInstr(MachineInstr &MI) override; +}; + +class TargetRegisterClass; +class RegisterBank; + +// Simple builder class to easily profile properties about MIs. +class GISelInstProfileBuilder { + FoldingSetNodeID &ID; + const MachineRegisterInfo &MRI; + +public: + GISelInstProfileBuilder(FoldingSetNodeID &ID, const MachineRegisterInfo &MRI) + : ID(ID), MRI(MRI) {} + // Profiling methods. + const GISelInstProfileBuilder &addNodeIDOpcode(unsigned Opc) const; + const GISelInstProfileBuilder &addNodeIDRegType(const LLT &Ty) const; + const GISelInstProfileBuilder &addNodeIDRegType(const unsigned) const; + + const GISelInstProfileBuilder & + addNodeIDRegType(const TargetRegisterClass *RC) const; + const GISelInstProfileBuilder &addNodeIDRegType(const RegisterBank *RB) const; + + const GISelInstProfileBuilder &addNodeIDRegNum(unsigned Reg) const; + + const GISelInstProfileBuilder &addNodeIDImmediate(int64_t Imm) const; + const GISelInstProfileBuilder & + addNodeIDMBB(const MachineBasicBlock *MBB) const; + + const GISelInstProfileBuilder & + addNodeIDMachineOperand(const MachineOperand &MO) const; + + const GISelInstProfileBuilder &addNodeIDFlag(unsigned Flag) const; + const GISelInstProfileBuilder &addNodeID(const MachineInstr *MI) const; +}; + +/// Simple wrapper that does the following. +/// 1) Lazily evaluate the MachineFunction to compute CSEable instructions. +/// 2) Allows configuration of which instructions are CSEd through CSEConfig +/// object. Provides a method called get which takes a CSEConfig object. +class GISelCSEAnalysisWrapper { + GISelCSEInfo Info; + MachineFunction *MF = nullptr; + bool AlreadyComputed = false; + +public: + /// Takes a CSEConfig object that defines what opcodes get CSEd. + /// If CSEConfig is already set, and the CSE Analysis has been preserved, + /// it will not use the new CSEOpt(use Recompute to force using the new + /// CSEOpt). + GISelCSEInfo &get(std::unique_ptr CSEOpt, bool ReCompute = false); + void setMF(MachineFunction &MFunc) { MF = &MFunc; } + void setComputed(bool Computed) { AlreadyComputed = Computed; } + void releaseMemory() { Info.releaseMemory(); } +}; + +/// The actual analysis pass wrapper. +class GISelCSEAnalysisWrapperPass : public MachineFunctionPass { + GISelCSEAnalysisWrapper Wrapper; + +public: + static char ID; + GISelCSEAnalysisWrapperPass() : MachineFunctionPass(ID) { + initializeGISelCSEAnalysisWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + const GISelCSEAnalysisWrapper &getCSEWrapper() const { return Wrapper; } + GISelCSEAnalysisWrapper &getCSEWrapper() { return Wrapper; } + + bool runOnMachineFunction(MachineFunction &MF) override; + + void releaseMemory() override { + Wrapper.releaseMemory(); + Wrapper.setComputed(false); + } +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h new file mode 100644 index 00000000000..a8fb736ebbb --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h @@ -0,0 +1,110 @@ +//===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file implements a version of MachineIRBuilder which CSEs insts within +/// a MachineBasicBlock. +//===----------------------------------------------------------------------===// +#ifndef LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H +#define LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H + +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" + +namespace llvm { + +/// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo. +/// Eg usage. +/// +/// +/// GISelCSEInfo *Info = +/// &getAnalysis().getCSEInfo(); CSEMIRBuilder +/// CB(Builder.getState()); CB.setCSEInfo(Info); auto A = CB.buildConstant(s32, +/// 42); auto B = CB.buildConstant(s32, 42); assert(A == B); unsigned CReg = +/// MRI.createGenericVirtualRegister(s32); auto C = CB.buildConstant(CReg, 42); +/// assert(C->getOpcode() == TargetOpcode::COPY); +/// Explicitly passing in a register would materialize a copy if possible. +/// CSEMIRBuilder also does trivial constant folding for binary ops. +class CSEMIRBuilder : public MachineIRBuilder { + + /// Returns true if A dominates B (within the same basic block). + /// Both iterators must be in the same basic block. + // + // TODO: Another approach for checking dominance is having two iterators and + // making them go towards each other until they meet or reach begin/end. Which + // approach is better? Should this even change dynamically? For G_CONSTANTS + // most of which will be at the top of the BB, the top down approach would be + // a better choice. Does IRTranslator placing constants at the beginning still + // make sense? Should this change based on Opcode? + bool dominates(MachineBasicBlock::const_iterator A, + MachineBasicBlock::const_iterator B) const; + + /// For given ID, find a machineinstr in the CSE Map. If found, check if it + /// dominates the current insertion point and if not, move it just before the + /// current insertion point and return it. If not found, return Null + /// MachineInstrBuilder. + MachineInstrBuilder getDominatingInstrForID(FoldingSetNodeID &ID, + void *&NodeInsertPos); + /// Simple check if we can CSE (we have the CSEInfo) or if this Opcode is + /// safe to CSE. + bool canPerformCSEForOpc(unsigned Opc) const; + + void profileDstOp(const DstOp &Op, GISelInstProfileBuilder &B) const; + + void profileDstOps(ArrayRef Ops, GISelInstProfileBuilder &B) const { + for (const DstOp &Op : Ops) + profileDstOp(Op, B); + } + + void profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const; + + void profileSrcOps(ArrayRef Ops, GISelInstProfileBuilder &B) const { + for (const SrcOp &Op : Ops) + profileSrcOp(Op, B); + } + + void profileMBBOpcode(GISelInstProfileBuilder &B, unsigned Opc) const; + + void profileEverything(unsigned Opc, ArrayRef DstOps, + ArrayRef SrcOps, Optional Flags, + GISelInstProfileBuilder &B) const; + + // Takes a MachineInstrBuilder and inserts it into the CSEMap using the + // NodeInsertPos. + MachineInstrBuilder memoizeMI(MachineInstrBuilder MIB, void *NodeInsertPos); + + // If we have can CSE an instruction, but still need to materialize to a VReg, + // we emit a copy from the CSE'd inst to the VReg. + MachineInstrBuilder generateCopiesIfRequired(ArrayRef DstOps, + MachineInstrBuilder &MIB); + + // If we have can CSE an instruction, but still need to materialize to a VReg, + // check if we can generate copies. It's not possible to return a single MIB, + // while emitting copies to multiple vregs. + bool checkCopyToDefsPossible(ArrayRef DstOps); + +public: + // Pull in base class constructors. + using MachineIRBuilder::MachineIRBuilder; + // Unhide buildInstr + MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, + ArrayRef SrcOps, + Optional Flag = None) override; + // Bring in the other overload from the base class. + using MachineIRBuilder::buildConstant; + + MachineInstrBuilder buildConstant(const DstOp &Res, + const ConstantInt &Val) override; + + // Bring in the other overload from the base class. + using MachineIRBuilder::buildFConstant; + MachineInstrBuilder buildFConstant(const DstOp &Res, + const ConstantFP &Val) override; +}; +} // namespace llvm +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index 58eb412d8c2..ab498e8f070 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -40,6 +40,7 @@ class Value; class CallLowering { const TargetLowering *TLI; + virtual void anchor(); public: struct ArgInfo { unsigned Reg; @@ -108,6 +109,9 @@ public: MachineIRBuilder &MIRBuilder; MachineRegisterInfo &MRI; CCAssignFn *AssignFn; + + private: + virtual void anchor(); }; protected: @@ -138,12 +142,12 @@ public: virtual ~CallLowering() = default; /// This hook must be implemented to lower outgoing return values, described - /// by \p Val, into the specified virtual register \p VReg. + /// by \p Val, into the specified virtual registers \p VRegs. /// This hook is used by GlobalISel. /// /// \return True if the lowering succeeds, false otherwise. - virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, - const Value *Val, unsigned VReg) const { + virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, + ArrayRef VRegs) const { return false; } diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h index 36a33deb4a6..b097c781776 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h @@ -21,6 +21,7 @@ namespace llvm { class MachineRegisterInfo; class CombinerInfo; +class GISelCSEInfo; class TargetPassConfig; class MachineFunction; @@ -28,14 +29,17 @@ class Combiner { public: Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC); - bool combineMachineInstrs(MachineFunction &MF); + /// If CSEInfo is not null, then the Combiner will setup observer for + /// CSEInfo and instantiate a CSEMIRBuilder. Pass nullptr if CSE is not + /// needed. + bool combineMachineInstrs(MachineFunction &MF, GISelCSEInfo *CSEInfo); protected: CombinerInfo &CInfo; MachineRegisterInfo *MRI = nullptr; const TargetPassConfig *TPC; - MachineIRBuilder Builder; + std::unique_ptr Builder; }; } // End namespace llvm. diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 5d5b8398452..6e9ac01c1ee 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -1,4 +1,4 @@ -//== llvm/CodeGen/GlobalISel/CombinerHelper.h -------------- -*- C++ -*-==// +//===-- llvm/CodeGen/GlobalISel/CombinerHelper.h --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -20,21 +20,36 @@ namespace llvm { +class GISelChangeObserver; class MachineIRBuilder; class MachineRegisterInfo; class MachineInstr; +class MachineOperand; class CombinerHelper { MachineIRBuilder &Builder; MachineRegisterInfo &MRI; + GISelChangeObserver &Observer; public: - CombinerHelper(MachineIRBuilder &B); + CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B); + + /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes + void replaceRegWith(MachineRegisterInfo &MRI, unsigned FromReg, unsigned ToReg) const; + + /// Replace a single register operand with a new register and inform the + /// observer of the changes. + void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, + unsigned ToReg) const; /// If \p MI is COPY, try to combine it. /// Returns true if MI changed. bool tryCombineCopy(MachineInstr &MI); + /// If \p MI is extend that consumes the result of a load, try to combine it. + /// Returns true if MI changed. + bool tryCombineExtendingLoads(MachineInstr &MI); + /// Try to transform \p MI by using all of the above /// combine functions. Returns true if changed. bool tryCombine(MachineInstr &MI); diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h index 1d248547adb..d21aa3f725d 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h @@ -17,10 +17,12 @@ #include namespace llvm { +class GISelChangeObserver; class LegalizerInfo; class MachineInstr; class MachineIRBuilder; class MachineRegisterInfo; + // Contains information relevant to enabling/disabling various combines for a // pass. class CombinerInfo { @@ -41,7 +43,19 @@ public: /// illegal ops that are created. bool LegalizeIllegalOps; // TODO: Make use of this. const LegalizerInfo *LInfo; - virtual bool combine(MachineInstr &MI, MachineIRBuilder &B) const = 0; + + /// Attempt to combine instructions using MI as the root. + /// + /// Use Observer to report the creation, modification, and erasure of + /// instructions. GISelChangeObserver will automatically report certain + /// kinds of operations. These operations are: + /// * Instructions that are newly inserted into the MachineFunction + /// * Instructions that are erased from the MachineFunction. + /// + /// However, it is important to report instruction modification and this is + /// not automatic. + virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, + MachineIRBuilder &B) const = 0; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h index 8d61f9a6827..220a571b21d 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h @@ -15,91 +15,20 @@ namespace llvm { -static Optional ConstantFoldBinOp(unsigned Opcode, const unsigned Op1, - const unsigned Op2, - const MachineRegisterInfo &MRI) { - auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI); - auto MaybeOp2Cst = getConstantVRegVal(Op2, MRI); - if (MaybeOp1Cst && MaybeOp2Cst) { - LLT Ty = MRI.getType(Op1); - APInt C1(Ty.getSizeInBits(), *MaybeOp1Cst, true); - APInt C2(Ty.getSizeInBits(), *MaybeOp2Cst, true); - switch (Opcode) { - default: - break; - case TargetOpcode::G_ADD: - return C1 + C2; - case TargetOpcode::G_AND: - return C1 & C2; - case TargetOpcode::G_ASHR: - return C1.ashr(C2); - case TargetOpcode::G_LSHR: - return C1.lshr(C2); - case TargetOpcode::G_MUL: - return C1 * C2; - case TargetOpcode::G_OR: - return C1 | C2; - case TargetOpcode::G_SHL: - return C1 << C2; - case TargetOpcode::G_SUB: - return C1 - C2; - case TargetOpcode::G_XOR: - return C1 ^ C2; - case TargetOpcode::G_UDIV: - if (!C2.getBoolValue()) - break; - return C1.udiv(C2); - case TargetOpcode::G_SDIV: - if (!C2.getBoolValue()) - break; - return C1.sdiv(C2); - case TargetOpcode::G_UREM: - if (!C2.getBoolValue()) - break; - return C1.urem(C2); - case TargetOpcode::G_SREM: - if (!C2.getBoolValue()) - break; - return C1.srem(C2); - } - } - return None; -} - /// An MIRBuilder which does trivial constant folding of binary ops. /// Calls to buildInstr will also try to constant fold binary ops. -class ConstantFoldingMIRBuilder - : public FoldableInstructionsBuilder { +class ConstantFoldingMIRBuilder : public MachineIRBuilder { public: // Pull in base class constructors. - using FoldableInstructionsBuilder< - ConstantFoldingMIRBuilder>::FoldableInstructionsBuilder; - // Unhide buildInstr - using FoldableInstructionsBuilder::buildInstr; + using MachineIRBuilder::MachineIRBuilder; - // Implement buildBinaryOp required by FoldableInstructionsBuilder which - // tries to constant fold. - MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst, - unsigned Src0, unsigned Src1) { - validateBinaryOp(Dst, Src0, Src1); - auto MaybeCst = ConstantFoldBinOp(Opcode, Src0, Src1, getMF().getRegInfo()); - if (MaybeCst) - return buildConstant(Dst, MaybeCst->getSExtValue()); - return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1); - } - - template - MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, UseArg1Ty &&Arg1, - UseArg2Ty &&Arg2) { - unsigned Dst = getDestFromArg(Ty); - return buildInstr(Opc, Dst, getRegFromArg(std::forward(Arg1)), - getRegFromArg(std::forward(Arg2))); - } + virtual ~ConstantFoldingMIRBuilder() = default; // Try to provide an overload for buildInstr for binary ops in order to // constant fold. - MachineInstrBuilder buildInstr(unsigned Opc, unsigned Dst, unsigned Src0, - unsigned Src1) { + MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, + ArrayRef SrcOps, + Optional Flags = None) override { switch (Opc) { default: break; @@ -116,19 +45,18 @@ public: case TargetOpcode::G_SDIV: case TargetOpcode::G_UREM: case TargetOpcode::G_SREM: { - return buildBinaryOp(Opc, Dst, Src0, Src1); + assert(DstOps.size() == 1 && "Invalid dst ops"); + assert(SrcOps.size() == 2 && "Invalid src ops"); + const DstOp &Dst = DstOps[0]; + const SrcOp &Src0 = SrcOps[0]; + const SrcOp &Src1 = SrcOps[1]; + if (auto MaybeCst = + ConstantFoldBinOp(Opc, Src0.getReg(), Src1.getReg(), *getMRI())) + return buildConstant(Dst, MaybeCst->getSExtValue()); + break; } } - return buildInstr(Opc).addDef(Dst).addUse(Src0).addUse(Src1); - } - - // Fallback implementation of buildInstr. - template - MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, - UseArgsTy &&... Args) { - auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty)); - addUsesFromArgs(MIB, std::forward(Args)...); - return MIB; + return MachineIRBuilder::buildInstr(Opc, DstOps, SrcOps); } }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h new file mode 100644 index 00000000000..c8e8a7a5a7c --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h @@ -0,0 +1,111 @@ +//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// This contains common code to allow clients to notify changes to machine +/// instr. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H +#define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { +class MachineInstr; +class MachineRegisterInfo; + +/// Abstract class that contains various methods for clients to notify about +/// changes. This should be the preferred way for APIs to notify changes. +/// Typically calling erasingInstr/createdInstr multiple times should not affect +/// the result. The observer would likely need to check if it was already +/// notified earlier (consider using GISelWorkList). +class GISelChangeObserver { + SmallPtrSet ChangingAllUsesOfReg; + +public: + virtual ~GISelChangeObserver() {} + + /// An instruction is about to be erased. + virtual void erasingInstr(MachineInstr &MI) = 0; + /// An instruction was created and inserted into the function. + virtual void createdInstr(MachineInstr &MI) = 0; + /// This instruction is about to be mutated in some way. + virtual void changingInstr(MachineInstr &MI) = 0; + /// This instruction was mutated in some way. + virtual void changedInstr(MachineInstr &MI) = 0; + + /// All the instructions using the given register are being changed. + /// For convenience, finishedChangingAllUsesOfReg() will report the completion + /// of the changes. The use list may change between this call and + /// finishedChangingAllUsesOfReg(). + void changingAllUsesOfReg(const MachineRegisterInfo &MRI, unsigned Reg); + /// All instructions reported as changing by changingAllUsesOfReg() have + /// finished being changed. + void finishedChangingAllUsesOfReg(); + +}; + +/// Simple wrapper observer that takes several observers, and calls +/// each one for each event. If there are multiple observers (say CSE, +/// Legalizer, Combiner), it's sufficient to register this to the machine +/// function as the delegate. +class GISelObserverWrapper : public MachineFunction::Delegate, + public GISelChangeObserver { + SmallVector Observers; + +public: + GISelObserverWrapper() = default; + GISelObserverWrapper(ArrayRef Obs) + : Observers(Obs.begin(), Obs.end()) {} + // Adds an observer. + void addObserver(GISelChangeObserver *O) { Observers.push_back(O); } + // Removes an observer from the list and does nothing if observer is not + // present. + void removeObserver(GISelChangeObserver *O) { + auto It = std::find(Observers.begin(), Observers.end(), O); + if (It != Observers.end()) + Observers.erase(It); + } + // API for Observer. + void erasingInstr(MachineInstr &MI) override { + for (auto &O : Observers) + O->erasingInstr(MI); + } + void createdInstr(MachineInstr &MI) override { + for (auto &O : Observers) + O->createdInstr(MI); + } + void changingInstr(MachineInstr &MI) override { + for (auto &O : Observers) + O->changingInstr(MI); + } + void changedInstr(MachineInstr &MI) override { + for (auto &O : Observers) + O->changedInstr(MI); + } + // API for MachineFunction::Delegate + void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); } + void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); } +}; + +/// A simple RAII based CSEInfo installer. +/// Use this in a scope to install a delegate to the MachineFunction and reset +/// it at the end of the scope. +class RAIIDelegateInstaller { + MachineFunction &MF; + MachineFunction::Delegate *Delegate; + +public: + RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del); + ~RAIIDelegateInstaller(); +}; + +} // namespace llvm +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h index 167905dc9aa..1571841a208 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h @@ -12,38 +12,42 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/Support/Debug.h" namespace llvm { class MachineInstr; +class MachineFunction; -// Worklist which mostly works similar to InstCombineWorkList, but on MachineInstrs. -// The main difference with something like a SetVector is that erasing an element doesn't -// move all elements over one place - instead just nulls out the element of the vector. -// FIXME: Does it make sense to factor out common code with the instcombinerWorkList? +// Worklist which mostly works similar to InstCombineWorkList, but on +// MachineInstrs. The main difference with something like a SetVector is that +// erasing an element doesn't move all elements over one place - instead just +// nulls out the element of the vector. +// +// FIXME: Does it make sense to factor out common code with the +// instcombinerWorkList? template class GISelWorkList { - SmallVector Worklist; - DenseMap WorklistMap; + SmallVector Worklist; + DenseMap WorklistMap; public: - GISelWorkList() = default; + GISelWorkList() {} bool empty() const { return WorklistMap.empty(); } unsigned size() const { return WorklistMap.size(); } - /// Add - Add the specified instruction to the worklist if it isn't already - /// in it. + /// Add the specified instruction to the worklist if it isn't already in it. void insert(MachineInstr *I) { - if (WorklistMap.try_emplace(I, Worklist.size()).second) { + if (WorklistMap.try_emplace(I, Worklist.size()).second) Worklist.push_back(I); - } } - /// Remove - remove I from the worklist if it exists. - void remove(MachineInstr *I) { + /// Remove I from the worklist if it exists. + void remove(const MachineInstr *I) { auto It = WorklistMap.find(I); if (It == WorklistMap.end()) return; // Not in worklist. @@ -53,6 +57,11 @@ public: WorklistMap.erase(It); } + void clear() { + Worklist.clear(); + WorklistMap.clear(); + } + MachineInstr *pop_back_val() { MachineInstr *I; do { diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 2498ee93321..d1770bf6e4c 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -21,11 +21,11 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Types.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/Allocator.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/Support/Allocator.h" #include #include @@ -300,6 +300,8 @@ private: bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder); + bool translateFNeg(const User &U, MachineIRBuilder &MIRBuilder); + bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder); } @@ -442,11 +444,13 @@ private: // I.e., compared to regular MIBuilder, this one also inserts the instruction // in the current block, it can creates block, etc., basically a kind of // IRBuilder, but for Machine IR. - MachineIRBuilder CurBuilder; + // CSEMIRBuilder CurBuilder; + std::unique_ptr CurBuilder; // Builder set to the entry block (just after ABI lowering instructions). Used // as a convenient location for Constants. - MachineIRBuilder EntryBuilder; + // CSEMIRBuilder EntryBuilder; + std::unique_ptr EntryBuilder; // The MachineFunction currently being translated. MachineFunction *MF; diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index 873587651ef..20bec765017 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h --===========// +//===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- C++ -*-// // // The LLVM Compiler Infrastructure // @@ -14,12 +14,14 @@ #include "llvm/CodeGen/GlobalISel/Legalizer.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" +#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "legalizer" +using namespace llvm::MIPatternMatch; namespace llvm { class LegalizationArtifactCombiner { @@ -36,15 +38,29 @@ public: SmallVectorImpl &DeadInsts) { if (MI.getOpcode() != TargetOpcode::G_ANYEXT) return false; - if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC, - MI.getOperand(1).getReg(), MRI)) { + + Builder.setInstr(MI); + unsigned DstReg = MI.getOperand(0).getReg(); + unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + + // aext(trunc x) - > aext/copy/trunc x + unsigned TruncSrc; + if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - unsigned DstReg = MI.getOperand(0).getReg(); - unsigned SrcReg = DefMI->getOperand(1).getReg(); - Builder.setInstr(MI); - // We get a copy/trunc/extend depending on the sizes - Builder.buildAnyExtOrTrunc(DstReg, SrcReg); - markInstAndDefDead(MI, *DefMI, DeadInsts); + Builder.buildAnyExtOrTrunc(DstReg, TruncSrc); + markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); + return true; + } + + // aext([asz]ext x) -> [asz]ext x + unsigned ExtSrc; + MachineInstr *ExtMI; + if (mi_match(SrcReg, MRI, + m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)), + m_GSExt(m_Reg(ExtSrc)), + m_GZExt(m_Reg(ExtSrc)))))) { + Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc}); + markInstAndDefDead(MI, *ExtMI, DeadInsts); return true; } return tryFoldImplicitDef(MI, DeadInsts); @@ -55,24 +71,25 @@ public: if (MI.getOpcode() != TargetOpcode::G_ZEXT) return false; - if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC, - MI.getOperand(1).getReg(), MRI)) { - unsigned DstReg = MI.getOperand(0).getReg(); + + Builder.setInstr(MI); + unsigned DstReg = MI.getOperand(0).getReg(); + unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + + // zext(trunc x) - > and (aext/copy/trunc x), mask + unsigned TruncSrc; + if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLT DstTy = MRI.getType(DstReg); if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) || isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - Builder.setInstr(MI); - unsigned ZExtSrc = MI.getOperand(1).getReg(); - LLT ZExtSrcTy = MRI.getType(ZExtSrc); - APInt Mask = APInt::getAllOnesValue(ZExtSrcTy.getSizeInBits()); - auto MaskCstMIB = Builder.buildConstant(DstTy, Mask.getZExtValue()); - unsigned TruncSrc = DefMI->getOperand(1).getReg(); - // We get a copy/trunc/extend depending on the sizes - auto SrcCopyOrTrunc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc); - Builder.buildAnd(DstReg, SrcCopyOrTrunc, MaskCstMIB); - markInstAndDefDead(MI, *DefMI, DeadInsts); + LLT SrcTy = MRI.getType(SrcReg); + APInt Mask = APInt::getAllOnesValue(SrcTy.getSizeInBits()); + auto MIBMask = Builder.buildConstant(DstTy, Mask.getZExtValue()); + Builder.buildAnd(DstReg, Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), + MIBMask); + markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); return true; } return tryFoldImplicitDef(MI, DeadInsts); @@ -83,33 +100,34 @@ public: if (MI.getOpcode() != TargetOpcode::G_SEXT) return false; - if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC, - MI.getOperand(1).getReg(), MRI)) { - unsigned DstReg = MI.getOperand(0).getReg(); + + Builder.setInstr(MI); + unsigned DstReg = MI.getOperand(0).getReg(); + unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + + // sext(trunc x) - > ashr (shl (aext/copy/trunc x), c), c + unsigned TruncSrc; + if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLT DstTy = MRI.getType(DstReg); if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) || isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) || isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); - Builder.setInstr(MI); - unsigned SExtSrc = MI.getOperand(1).getReg(); - LLT SExtSrcTy = MRI.getType(SExtSrc); - unsigned SizeDiff = DstTy.getSizeInBits() - SExtSrcTy.getSizeInBits(); - auto SizeDiffMIB = Builder.buildConstant(DstTy, SizeDiff); - unsigned TruncSrcReg = DefMI->getOperand(1).getReg(); - // We get a copy/trunc/extend depending on the sizes - auto SrcCopyExtOrTrunc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrcReg); - auto ShlMIB = Builder.buildInstr(TargetOpcode::G_SHL, DstTy, - SrcCopyExtOrTrunc, SizeDiffMIB); - Builder.buildInstr(TargetOpcode::G_ASHR, DstReg, ShlMIB, SizeDiffMIB); - markInstAndDefDead(MI, *DefMI, DeadInsts); + LLT SrcTy = MRI.getType(SrcReg); + unsigned ShAmt = DstTy.getSizeInBits() - SrcTy.getSizeInBits(); + auto MIBShAmt = Builder.buildConstant(DstTy, ShAmt); + auto MIBShl = Builder.buildInstr( + TargetOpcode::G_SHL, {DstTy}, + {Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), MIBShAmt}); + Builder.buildInstr(TargetOpcode::G_ASHR, {DstReg}, {MIBShl, MIBShAmt}); + markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); return true; } return tryFoldImplicitDef(MI, DeadInsts); } - /// Try to fold sb = EXTEND (G_IMPLICIT_DEF sa) -> sb = G_IMPLICIT_DEF + /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF). bool tryFoldImplicitDef(MachineInstr &MI, SmallVectorImpl &DeadInsts) { unsigned Opcode = MI.getOpcode(); @@ -119,13 +137,25 @@ public: if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(1).getReg(), MRI)) { + Builder.setInstr(MI); unsigned DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) - return false; - LLVM_DEBUG(dbgs() << ".. Combine EXT(IMPLICIT_DEF) " << MI;); - Builder.setInstr(MI); - Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, DstReg); + + if (Opcode == TargetOpcode::G_ANYEXT) { + // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF + if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) + return false; + LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;); + Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {}); + } else { + // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top + // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT. + if (isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) + return false; + LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;); + Builder.buildConstant(DstReg, 0); + } + markInstAndDefDead(MI, *DefMI, DeadInsts); return true; } @@ -139,8 +169,20 @@ public: return false; unsigned NumDefs = MI.getNumOperands() - 1; - MachineInstr *MergeI = getOpcodeDef(TargetOpcode::G_MERGE_VALUES, - MI.getOperand(NumDefs).getReg(), MRI); + + unsigned MergingOpcode; + LLT OpTy = MRI.getType(MI.getOperand(NumDefs).getReg()); + LLT DestTy = MRI.getType(MI.getOperand(0).getReg()); + if (OpTy.isVector() && DestTy.isVector()) + MergingOpcode = TargetOpcode::G_CONCAT_VECTORS; + else if (OpTy.isVector() && !DestTy.isVector()) + MergingOpcode = TargetOpcode::G_BUILD_VECTOR; + else + MergingOpcode = TargetOpcode::G_MERGE_VALUES; + + MachineInstr *MergeI = + getOpcodeDef(MergingOpcode, MI.getOperand(NumDefs).getReg(), MRI); + if (!MergeI) return false; @@ -277,6 +319,19 @@ private: auto Step = LI.getAction(Query); return Step.Action == Unsupported || Step.Action == NotFound; } + + /// Looks through copy instructions and returns the actual + /// source register. + unsigned lookThroughCopyInstrs(unsigned Reg) { + unsigned TmpReg; + while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) { + if (MRI.getType(TmpReg).isValid()) + Reg = TmpReg; + else + break; + } + return Reg; + } }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index d122e67b87b..9b4ecf9284e 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -32,6 +32,7 @@ namespace llvm { class LegalizerInfo; class Legalizer; class MachineRegisterInfo; +class GISelChangeObserver; class LegalizerHelper { public: @@ -48,7 +49,10 @@ public: UnableToLegalize, }; - LegalizerHelper(MachineFunction &MF); + LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, + MachineIRBuilder &B); + LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI, + GISelChangeObserver &Observer, MachineIRBuilder &B); /// Replace \p MI by a sequence of legal instructions that can implement the /// same operation. Note that this means \p MI may be deleted, so any iterator @@ -87,7 +91,7 @@ public: /// Expose MIRBuilder so clients can set their own RecordInsertInstruction /// functions - MachineIRBuilder MIRBuilder; + MachineIRBuilder &MIRBuilder; /// Expose LegalizerInfo so the clients can re-use. const LegalizerInfo &getLegalizerInfo() const { return LI; } @@ -112,8 +116,12 @@ private: void extractParts(unsigned Reg, LLT Ty, int NumParts, SmallVectorImpl &VRegs); + LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + MachineRegisterInfo &MRI; const LegalizerInfo &LI; + /// To keep track of changes made by the LegalizerHelper. + GISelChangeObserver &Observer; }; /// Helper function that creates the given libcall. diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index a8c26082f22..13776dd3e87 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -39,6 +39,7 @@ class MachineInstr; class MachineIRBuilder; class MachineRegisterInfo; class MCInstrInfo; +class GISelChangeObserver; namespace LegalizeActions { enum LegalizeAction : std::uint8_t { @@ -121,7 +122,7 @@ struct LegalityQuery { ArrayRef Types; struct MemDesc { - uint64_t Size; + uint64_t SizeInBits; AtomicOrdering Ordering; }; @@ -651,6 +652,20 @@ public: return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy); } + /// Widen the scalar to match the size of another. + LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) { + typeIdx(TypeIdx); + return widenScalarIf( + [=](const LegalityQuery &Query) { + return Query.Types[LargeTypeIdx].getScalarSizeInBits() > + Query.Types[TypeIdx].getSizeInBits(); + }, + [=](const LegalityQuery &Query) { + return std::make_pair(TypeIdx, + Query.Types[LargeTypeIdx].getElementType()); + }); + } + /// Add more elements to the vector to reach the next power of two. /// No effect if the type is not a vector or the element count is a power of /// two. @@ -693,6 +708,8 @@ public: }, [=](const LegalityQuery &Query) { LLT VecTy = Query.Types[TypeIdx]; + if (MaxElements == 1) + return std::make_pair(TypeIdx, VecTy.getElementType()); return std::make_pair( TypeIdx, LLT::vector(MaxElements, VecTy.getScalarSizeInBits())); }); @@ -947,9 +964,9 @@ public: bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; - virtual bool legalizeCustom(MachineInstr &MI, - MachineRegisterInfo &MRI, - MachineIRBuilder &MIRBuilder) const; + virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder, + GISelChangeObserver &Observer) const; private: /// Determine what action should be taken to legalize the given generic diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index ac1673de5f3..37de8f03041 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H #define LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H +#include "llvm/CodeGen/GlobalISel/CSEInfo.h" #include "llvm/CodeGen/GlobalISel/Types.h" #include "llvm/CodeGen/LowLevelType.h" @@ -30,6 +31,7 @@ namespace llvm { class MachineFunction; class MachineInstr; class TargetInstrInfo; +class GISelChangeObserver; /// Class which stores all the state required in a MachineIRBuilder. /// Since MachineIRBuilders will only store state in this object, it allows @@ -50,63 +52,178 @@ struct MachineIRBuilderState { MachineBasicBlock::iterator II; /// @} - std::function InsertedInstr; + GISelChangeObserver *Observer; + + GISelCSEInfo *CSEInfo; }; +class DstOp { + union { + LLT LLTTy; + unsigned Reg; + const TargetRegisterClass *RC; + }; + +public: + enum class DstType { Ty_LLT, Ty_Reg, Ty_RC }; + DstOp(unsigned R) : Reg(R), Ty(DstType::Ty_Reg) {} + DstOp(const LLT &T) : LLTTy(T), Ty(DstType::Ty_LLT) {} + DstOp(const TargetRegisterClass *TRC) : RC(TRC), Ty(DstType::Ty_RC) {} + + void addDefToMIB(MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) const { + switch (Ty) { + case DstType::Ty_Reg: + MIB.addDef(Reg); + break; + case DstType::Ty_LLT: + MIB.addDef(MRI.createGenericVirtualRegister(LLTTy)); + break; + case DstType::Ty_RC: + MIB.addDef(MRI.createVirtualRegister(RC)); + break; + } + } + + LLT getLLTTy(const MachineRegisterInfo &MRI) const { + switch (Ty) { + case DstType::Ty_RC: + return LLT{}; + case DstType::Ty_LLT: + return LLTTy; + case DstType::Ty_Reg: + return MRI.getType(Reg); + } + llvm_unreachable("Unrecognised DstOp::DstType enum"); + } + + unsigned getReg() const { + assert(Ty == DstType::Ty_Reg && "Not a register"); + return Reg; + } + + const TargetRegisterClass *getRegClass() const { + switch (Ty) { + case DstType::Ty_RC: + return RC; + default: + llvm_unreachable("Not a RC Operand"); + } + } + + DstType getDstOpKind() const { return Ty; } + +private: + DstType Ty; +}; + +class SrcOp { + union { + MachineInstrBuilder SrcMIB; + unsigned Reg; + CmpInst::Predicate Pred; + }; + +public: + enum class SrcType { Ty_Reg, Ty_MIB, Ty_Predicate }; + SrcOp(unsigned R) : Reg(R), Ty(SrcType::Ty_Reg) {} + SrcOp(const MachineInstrBuilder &MIB) : SrcMIB(MIB), Ty(SrcType::Ty_MIB) {} + SrcOp(const CmpInst::Predicate P) : Pred(P), Ty(SrcType::Ty_Predicate) {} + + void addSrcToMIB(MachineInstrBuilder &MIB) const { + switch (Ty) { + case SrcType::Ty_Predicate: + MIB.addPredicate(Pred); + break; + case SrcType::Ty_Reg: + MIB.addUse(Reg); + break; + case SrcType::Ty_MIB: + MIB.addUse(SrcMIB->getOperand(0).getReg()); + break; + } + } + + LLT getLLTTy(const MachineRegisterInfo &MRI) const { + switch (Ty) { + case SrcType::Ty_Predicate: + llvm_unreachable("Not a register operand"); + case SrcType::Ty_Reg: + return MRI.getType(Reg); + case SrcType::Ty_MIB: + return MRI.getType(SrcMIB->getOperand(0).getReg()); + } + llvm_unreachable("Unrecognised SrcOp::SrcType enum"); + } + + unsigned getReg() const { + switch (Ty) { + case SrcType::Ty_Predicate: + llvm_unreachable("Not a register operand"); + case SrcType::Ty_Reg: + return Reg; + case SrcType::Ty_MIB: + return SrcMIB->getOperand(0).getReg(); + } + llvm_unreachable("Unrecognised SrcOp::SrcType enum"); + } + + CmpInst::Predicate getPredicate() const { + switch (Ty) { + case SrcType::Ty_Predicate: + return Pred; + default: + llvm_unreachable("Not a register operand"); + } + } + + SrcType getSrcOpKind() const { return Ty; } + +private: + SrcType Ty; +}; + +class FlagsOp { + Optional Flags; + +public: + explicit FlagsOp(unsigned F) : Flags(F) {} + FlagsOp() : Flags(None) {} + Optional getFlags() const { return Flags; } +}; /// Helper class to build MachineInstr. /// It keeps internally the insertion point and debug location for all /// the new instructions we want to create. /// This information can be modify via the related setters. -class MachineIRBuilderBase { +class MachineIRBuilder { MachineIRBuilderState State; + +protected: + void validateTruncExt(const LLT &Dst, const LLT &Src, bool IsExtend); + + void validateBinaryOp(const LLT &Res, const LLT &Op0, const LLT &Op1); + + void validateSelectOp(const LLT &ResTy, const LLT &TstTy, const LLT &Op0Ty, + const LLT &Op1Ty); + void recordInsertion(MachineInstr *MI) const; + +public: + /// Some constructors for easy use. + MachineIRBuilder() = default; + MachineIRBuilder(MachineFunction &MF) { setMF(MF); } + MachineIRBuilder(MachineInstr &MI) : MachineIRBuilder(*MI.getMF()) { + setInstr(MI); + } + + virtual ~MachineIRBuilder() = default; + + MachineIRBuilder(const MachineIRBuilderState &BState) : State(BState) {} + const TargetInstrInfo &getTII() { assert(State.TII && "TargetInstrInfo is not set"); return *State.TII; } - void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend); - -protected: - unsigned getDestFromArg(unsigned Reg) { return Reg; } - unsigned getDestFromArg(LLT Ty) { - return getMF().getRegInfo().createGenericVirtualRegister(Ty); - } - unsigned getDestFromArg(const TargetRegisterClass *RC) { - return getMF().getRegInfo().createVirtualRegister(RC); - } - - void addUseFromArg(MachineInstrBuilder &MIB, unsigned Reg) { - MIB.addUse(Reg); - } - - void addUseFromArg(MachineInstrBuilder &MIB, const MachineInstrBuilder &UseMIB) { - MIB.addUse(UseMIB->getOperand(0).getReg()); - } - - void addUsesFromArgs(MachineInstrBuilder &MIB) { } - template - void addUsesFromArgs(MachineInstrBuilder &MIB, UseArgTy &&Arg1, UseArgsTy &&... Args) { - addUseFromArg(MIB, Arg1); - addUsesFromArgs(MIB, std::forward(Args)...); - } - unsigned getRegFromArg(unsigned Reg) { return Reg; } - unsigned getRegFromArg(const MachineInstrBuilder &MIB) { - return MIB->getOperand(0).getReg(); - } - - void validateBinaryOp(unsigned Res, unsigned Op0, unsigned Op1); - -public: - /// Some constructors for easy use. - MachineIRBuilderBase() = default; - MachineIRBuilderBase(MachineFunction &MF) { setMF(MF); } - MachineIRBuilderBase(MachineInstr &MI) : MachineIRBuilderBase(*MI.getMF()) { - setInstr(MI); - } - - MachineIRBuilderBase(const MachineIRBuilderState &BState) : State(BState) {} - /// Getter for the function we currently build. MachineFunction &getMF() { assert(State.MF && "MachineFunction is not set"); @@ -118,16 +235,25 @@ public: /// Getter for MRI MachineRegisterInfo *getMRI() { return State.MRI; } + const MachineRegisterInfo *getMRI() const { return State.MRI; } /// Getter for the State MachineIRBuilderState &getState() { return State; } /// Getter for the basic block we currently build. - MachineBasicBlock &getMBB() { + const MachineBasicBlock &getMBB() const { assert(State.MBB && "MachineBasicBlock is not set"); return *State.MBB; } + MachineBasicBlock &getMBB() { + return const_cast( + const_cast(this)->getMBB()); + } + + GISelCSEInfo *getCSEInfo() { return State.CSEInfo; } + const GISelCSEInfo *getCSEInfo() const { return State.CSEInfo; } + /// Current insertion point for new instructions. MachineBasicBlock::iterator getInsertPt() { return State.II; } @@ -137,10 +263,12 @@ public: void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II); /// @} + void setCSEInfo(GISelCSEInfo *Info); + /// \name Setters for the insertion point. /// @{ /// Set the MachineFunction where to build instructions. - void setMF(MachineFunction &); + void setMF(MachineFunction &MF); /// Set the insertion point to the end of \p MBB. /// \pre \p MBB must be contained by getMF(). @@ -151,12 +279,8 @@ public: void setInstr(MachineInstr &MI); /// @} - /// \name Control where instructions we create are recorded (typically for - /// visiting again later during legalization). - /// @{ - void recordInsertion(MachineInstr *InsertedInstr) const; - void recordInsertions(std::function InsertedInstr); - void stopRecordingInsertions(); + void setChangeObserver(GISelChangeObserver &Observer); + void stopObservingChanges(); /// @} /// Set the debug location to \p DL for all the next build instructions. @@ -208,6 +332,10 @@ public: const MDNode *Variable, const MDNode *Expr); + /// Build and insert a DBG_LABEL instructions specifying that \p Label is + /// given. Convert "llvm.dbg.label Label" to "DBG_LABEL Label". + MachineInstrBuilder buildDbgLabel(const MDNode *Label); + /// Build and insert \p Res = G_FRAME_INDEX \p Idx /// /// G_FRAME_INDEX materializes the address of an alloca value or other @@ -296,9 +424,9 @@ public: /// registers with the same scalar type (typically s1) /// /// \return The newly created instruction. - MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0, - unsigned Op1, unsigned CarryIn); - + MachineInstrBuilder buildUAdde(const DstOp &Res, const DstOp &CarryOut, + const SrcOp &Op0, const SrcOp &Op1, + const SrcOp &CarryIn); /// Build and insert \p Res = G_ANYEXT \p Op0 /// @@ -314,11 +442,7 @@ public: /// /// \return The newly created instruction. - MachineInstrBuilder buildAnyExt(unsigned Res, unsigned Op); - template - MachineInstrBuilder buildAnyExt(DstType &&Res, ArgType &&Arg) { - return buildAnyExt(getDestFromArg(Res), getRegFromArg(Arg)); - } + MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op); /// Build and insert \p Res = G_SEXT \p Op /// @@ -332,11 +456,7 @@ public: /// \pre \p Op must be smaller than \p Res /// /// \return The newly created instruction. - template - MachineInstrBuilder buildSExt(DstType &&Res, ArgType &&Arg) { - return buildSExt(getDestFromArg(Res), getRegFromArg(Arg)); - } - MachineInstrBuilder buildSExt(unsigned Res, unsigned Op); + MachineInstrBuilder buildSExt(const DstOp &Res, const SrcOp &Op); /// Build and insert \p Res = G_ZEXT \p Op /// @@ -350,11 +470,7 @@ public: /// \pre \p Op must be smaller than \p Res /// /// \return The newly created instruction. - template - MachineInstrBuilder buildZExt(DstType &&Res, ArgType &&Arg) { - return buildZExt(getDestFromArg(Res), getRegFromArg(Arg)); - } - MachineInstrBuilder buildZExt(unsigned Res, unsigned Op); + MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op); /// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. @@ -364,11 +480,7 @@ public: /// \pre \p Op must be a generic virtual register with scalar or vector type. /// /// \return The newly created instruction. - template - MachineInstrBuilder buildSExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) { - return buildSExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use)); - } - MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op); + MachineInstrBuilder buildSExtOrTrunc(const DstOp &Res, const SrcOp &Op); /// Build and insert \p Res = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. @@ -378,11 +490,7 @@ public: /// \pre \p Op must be a generic virtual register with scalar or vector type. /// /// \return The newly created instruction. - template - MachineInstrBuilder buildZExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) { - return buildZExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use)); - } - MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op); + MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op); // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. @@ -392,11 +500,7 @@ public: /// \pre \p Op must be a generic virtual register with scalar or vector type. /// /// \return The newly created instruction. - template - MachineInstrBuilder buildAnyExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) { - return buildAnyExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use)); - } - MachineInstrBuilder buildAnyExtOrTrunc(unsigned Res, unsigned Op); + MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op); /// Build and insert \p Res = \p ExtOpc, \p Res = G_TRUNC \p /// Op, or \p Res = COPY \p Op depending on the differing sizes of \p Res and @@ -407,15 +511,11 @@ public: /// \pre \p Op must be a generic virtual register with scalar or vector type. /// /// \return The newly created instruction. - MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, unsigned Res, - unsigned Op); + MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, const DstOp &Res, + const SrcOp &Op); /// Build and insert an appropriate cast between two registers of equal size. - template - MachineInstrBuilder buildCast(DstType &&Res, ArgType &&Arg) { - return buildCast(getDestFromArg(Res), getRegFromArg(Arg)); - } - MachineInstrBuilder buildCast(unsigned Dst, unsigned Src); + MachineInstrBuilder buildCast(const DstOp &Dst, const SrcOp &Src); /// Build and insert G_BR \p Dest /// @@ -460,7 +560,8 @@ public: /// type. /// /// \return The newly created instruction. - MachineInstrBuilder buildConstant(unsigned Res, const ConstantInt &Val); + virtual MachineInstrBuilder buildConstant(const DstOp &Res, + const ConstantInt &Val); /// Build and insert \p Res = G_CONSTANT \p Val /// @@ -470,12 +571,8 @@ public: /// \pre \p Res must be a generic virtual register with scalar type. /// /// \return The newly created instruction. - MachineInstrBuilder buildConstant(unsigned Res, int64_t Val); + MachineInstrBuilder buildConstant(const DstOp &Res, int64_t Val); - template - MachineInstrBuilder buildConstant(DstType &&Res, int64_t Val) { - return buildConstant(getDestFromArg(Res), Val); - } /// Build and insert \p Res = G_FCONSTANT \p Val /// /// G_FCONSTANT is a floating-point constant with the specified size and @@ -485,17 +582,10 @@ public: /// \pre \p Res must be a generic virtual register with scalar type. /// /// \return The newly created instruction. - template - MachineInstrBuilder buildFConstant(DstType &&Res, const ConstantFP &Val) { - return buildFConstant(getDestFromArg(Res), Val); - } - MachineInstrBuilder buildFConstant(unsigned Res, const ConstantFP &Val); + virtual MachineInstrBuilder buildFConstant(const DstOp &Res, + const ConstantFP &Val); - template - MachineInstrBuilder buildFConstant(DstType &&Res, double Val) { - return buildFConstant(getDestFromArg(Res), Val); - } - MachineInstrBuilder buildFConstant(unsigned Res, double Val); + MachineInstrBuilder buildFConstant(const DstOp &Res, double Val); /// Build and insert \p Res = COPY Op /// @@ -504,11 +594,7 @@ public: /// \pre setBasicBlock or setMI must have been called. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildCopy(unsigned Res, unsigned Op); - template - MachineInstrBuilder buildCopy(DstType &&Res, SrcType &&Src) { - return buildCopy(getDestFromArg(Res), getRegFromArg(Src)); - } + MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op); /// Build and insert `Res = G_LOAD Addr, MMO`. /// @@ -555,10 +641,7 @@ public: MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index); /// Build and insert \p Res = IMPLICIT_DEF. - template MachineInstrBuilder buildUndef(DstType &&Res) { - return buildUndef(getDestFromArg(Res)); - } - MachineInstrBuilder buildUndef(unsigned Res); + MachineInstrBuilder buildUndef(const DstOp &Res); /// Build and insert instructions to put \p Ops together at the specified p /// Indices to form a larger register. @@ -587,7 +670,7 @@ public: /// \pre The type of all \p Ops registers must be identical. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMerge(unsigned Res, ArrayRef Ops); + MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef Ops); /// Build and insert \p Res0, ... = G_UNMERGE_VALUES \p Op /// @@ -599,7 +682,50 @@ public: /// \pre The type of all \p Res registers must be identical. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildUnmerge(ArrayRef Res, unsigned Op); + MachineInstrBuilder buildUnmerge(ArrayRef Res, const SrcOp &Op); + MachineInstrBuilder buildUnmerge(ArrayRef Res, const SrcOp &Op); + + /// Build and insert \p Res = G_BUILD_VECTOR \p Op0, ... + /// + /// G_BUILD_VECTOR creates a vector value from multiple scalar registers. + /// \pre setBasicBlock or setMI must have been called. + /// \pre The entire register \p Res (and no more) must be covered by the + /// input scalar registers. + /// \pre The type of all \p Ops registers must be identical. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildBuildVector(const DstOp &Res, + ArrayRef Ops); + + /// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ... + /// + /// G_BUILD_VECTOR_TRUNC creates a vector value from multiple scalar registers + /// which have types larger than the destination vector element type, and + /// truncates the values to fit. + /// + /// If the operands given are already the same size as the vector elt type, + /// then this method will instead create a G_BUILD_VECTOR instruction. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre The type of all \p Ops registers must be identical. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildBuildVectorTrunc(const DstOp &Res, + ArrayRef Ops); + + /// Build and insert \p Res = G_CONCAT_VECTORS \p Op0, ... + /// + /// G_CONCAT_VECTORS creates a vector from the concatenation of 2 or more + /// vectors. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre The entire register \p Res (and no more) must be covered by the input + /// registers. + /// \pre The type of all source operands must be identical. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildConcatVectors(const DstOp &Res, + ArrayRef Ops); MachineInstrBuilder buildInsert(unsigned Res, unsigned Src, unsigned Op, unsigned Index); @@ -627,11 +753,7 @@ public: /// \pre \p Res must be smaller than \p Op /// /// \return The newly created instruction. - template - MachineInstrBuilder buildFPTrunc(DstType &&Res, SrcType &&Src) { - return buildFPTrunc(getDestFromArg(Res), getRegFromArg(Src)); - } - MachineInstrBuilder buildFPTrunc(unsigned Res, unsigned Op); + MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op); /// Build and insert \p Res = G_TRUNC \p Op /// @@ -644,11 +766,7 @@ public: /// \pre \p Res must be smaller than \p Op /// /// \return The newly created instruction. - MachineInstrBuilder buildTrunc(unsigned Res, unsigned Op); - template - MachineInstrBuilder buildTrunc(DstType &&Res, SrcType &&Src) { - return buildTrunc(getDestFromArg(Res), getRegFromArg(Src)); - } + MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op); /// Build and insert a \p Res = G_ICMP \p Pred, \p Op0, \p Op1 /// @@ -662,8 +780,8 @@ public: /// \pre \p Pred must be an integer predicate. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, - unsigned Res, unsigned Op0, unsigned Op1); + MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, + const SrcOp &Op0, const SrcOp &Op1); /// Build and insert a \p Res = G_FCMP \p Pred\p Op0, \p Op1 /// @@ -677,8 +795,8 @@ public: /// \pre \p Pred must be a floating-point predicate. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred, - unsigned Res, unsigned Op0, unsigned Op1); + MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred, const DstOp &Res, + const SrcOp &Op0, const SrcOp &Op1); /// Build and insert a \p Res = G_SELECT \p Tst, \p Op0, \p Op1 /// @@ -690,8 +808,8 @@ public: /// elements as the other parameters. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildSelect(unsigned Res, unsigned Tst, - unsigned Op0, unsigned Op1); + MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, + const SrcOp &Op0, const SrcOp &Op1); /// Build and insert \p Res = G_INSERT_VECTOR_ELT \p Val, /// \p Elt, \p Idx @@ -703,8 +821,10 @@ public: /// with scalar type. /// /// \return The newly created instruction. - MachineInstrBuilder buildInsertVectorElement(unsigned Res, unsigned Val, - unsigned Elt, unsigned Idx); + MachineInstrBuilder buildInsertVectorElement(const DstOp &Res, + const SrcOp &Val, + const SrcOp &Elt, + const SrcOp &Idx); /// Build and insert \p Res = G_EXTRACT_VECTOR_ELT \p Val, \p Idx /// @@ -714,8 +834,9 @@ public: /// \pre \p Idx must be a generic virtual register with scalar type. /// /// \return The newly created instruction. - MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val, - unsigned Idx); + MachineInstrBuilder buildExtractVectorElement(const DstOp &Res, + const SrcOp &Val, + const SrcOp &Idx); /// Build and insert `OldValRes, SuccessRes = /// G_ATOMIC_CMPXCHG_WITH_SUCCESS Addr, CmpVal, NewVal, MMO`. @@ -952,19 +1073,7 @@ public: /// /// \return The newly created instruction. MachineInstrBuilder buildBlockAddress(unsigned Res, const BlockAddress *BA); -}; -/// A CRTP class that contains methods for building instructions that can -/// be constant folded. MachineIRBuilders that want to inherit from this will -/// need to implement buildBinaryOp (for constant folding binary ops). -/// Alternatively, they can implement buildInstr(Opc, Dst, Uses...) to perform -/// additional folding for Opc. -template -class FoldableInstructionsBuilder : public MachineIRBuilderBase { - Base &base() { return static_cast(*this); } - -public: - using MachineIRBuilderBase::MachineIRBuilderBase; /// Build and insert \p Res = G_ADD \p Op0, \p Op1 /// /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1, @@ -976,13 +1085,10 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAdd(unsigned Dst, unsigned Src0, unsigned Src1) { - return base().buildBinaryOp(TargetOpcode::G_ADD, Dst, Src0, Src1); - } - template - MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) { - unsigned Res = base().getDestFromArg(Ty); - return base().buildAdd(Res, (base().getRegFromArg(UseArgs))...); + MachineInstrBuilder buildAdd(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional Flags = None) { + return buildInstr(TargetOpcode::G_ADD, {Dst}, {Src0, Src1}, Flags); } /// Build and insert \p Res = G_SUB \p Op0, \p Op1 @@ -996,13 +1102,10 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildSub(unsigned Dst, unsigned Src0, unsigned Src1) { - return base().buildBinaryOp(TargetOpcode::G_SUB, Dst, Src0, Src1); - } - template - MachineInstrBuilder buildSub(DstTy &&Ty, UseArgsTy &&... UseArgs) { - unsigned Res = base().getDestFromArg(Ty); - return base().buildSub(Res, (base().getRegFromArg(UseArgs))...); + MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional Flags = None) { + return buildInstr(TargetOpcode::G_SUB, {Dst}, {Src0, Src1}, Flags); } /// Build and insert \p Res = G_MUL \p Op0, \p Op1 @@ -1015,13 +1118,10 @@ public: /// with the same (scalar or vector) type). /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMul(unsigned Dst, unsigned Src0, unsigned Src1) { - return base().buildBinaryOp(TargetOpcode::G_MUL, Dst, Src0, Src1); - } - template - MachineInstrBuilder buildMul(DstTy &&Ty, UseArgsTy &&... UseArgs) { - unsigned Res = base().getDestFromArg(Ty); - return base().buildMul(Res, (base().getRegFromArg(UseArgs))...); + MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional Flags = None) { + return buildInstr(TargetOpcode::G_MUL, {Dst}, {Src0, Src1}, Flags); } /// Build and insert \p Res = G_AND \p Op0, \p Op1 @@ -1035,13 +1135,9 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAnd(unsigned Dst, unsigned Src0, unsigned Src1) { - return base().buildBinaryOp(TargetOpcode::G_AND, Dst, Src0, Src1); - } - template - MachineInstrBuilder buildAnd(DstTy &&Ty, UseArgsTy &&... UseArgs) { - unsigned Res = base().getDestFromArg(Ty); - return base().buildAnd(Res, (base().getRegFromArg(UseArgs))...); + MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_AND, {Dst}, {Src0, Src1}); } /// Build and insert \p Res = G_OR \p Op0, \p Op1 @@ -1054,39 +1150,14 @@ public: /// with the same (scalar or vector) type). /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildOr(unsigned Dst, unsigned Src0, unsigned Src1) { - return base().buildBinaryOp(TargetOpcode::G_OR, Dst, Src0, Src1); + MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_OR, {Dst}, {Src0, Src1}); } - template - MachineInstrBuilder buildOr(DstTy &&Ty, UseArgsTy &&... UseArgs) { - unsigned Res = base().getDestFromArg(Ty); - return base().buildOr(Res, (base().getRegFromArg(UseArgs))...); - } -}; -class MachineIRBuilder : public FoldableInstructionsBuilder { -public: - using FoldableInstructionsBuilder< - MachineIRBuilder>::FoldableInstructionsBuilder; - MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst, - unsigned Src0, unsigned Src1) { - validateBinaryOp(Dst, Src0, Src1); - return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1); - } - using FoldableInstructionsBuilder::buildInstr; - /// DAG like Generic method for building arbitrary instructions as above. - /// \Opc opcode for the instruction. - /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst - /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder) - /// Uses of type MachineInstrBuilder will perform - /// getOperand(0).getReg() to convert to register. - template - MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, - UseArgsTy &&... Args) { - auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty)); - addUsesFromArgs(MIB, std::forward(Args)...); - return MIB; - } + virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, + ArrayRef SrcOps, + Optional Flags = None); }; } // End namespace llvm. diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 82fd7eddb68..c33b32b2db4 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -103,8 +103,8 @@ public: /// Currently the TableGen-like file would look like: /// \code /// PartialMapping[] = { - /// /*32-bit add*/ {0, 32, GPR}, - /// /*2x32-bit add*/ {0, 32, GPR}, {0, 32, GPR}, // <-- Same entry 3x + /// /*32-bit add*/ {0, 32, GPR}, // Scalar entry repeated for first vec elt. + /// /*2x32-bit add*/ {0, 32, GPR}, {32, 32, GPR}, /// /*<2x32-bit> vadd {0, 64, VPR} /// }; // PartialMapping duplicated. /// @@ -118,14 +118,15 @@ public: /// With the array of pointer, we would have: /// \code /// PartialMapping[] = { - /// /*32-bit add*/ {0, 32, GPR}, + /// /*32-bit add lower */ {0, 32, GPR}, + /// /*32-bit add upper */ {32, 32, GPR}, /// /*<2x32-bit> vadd {0, 64, VPR} /// }; // No more duplication. /// /// BreakDowns[] = { /// /*AddBreakDown*/ &PartialMapping[0], - /// /*2xAddBreakDown*/ &PartialMapping[0], &PartialMapping[0], - /// /*VAddBreakDown*/ &PartialMapping[1] + /// /*2xAddBreakDown*/ &PartialMapping[0], &PartialMapping[1], + /// /*VAddBreakDown*/ &PartialMapping[2] /// }; // Addresses of PartialMapping duplicated (smaller). /// /// ValueMapping[] { diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h index 51e3a273297..82b791d35b2 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -108,5 +108,8 @@ APFloat getAPFloatFromSize(double Val, unsigned Size); /// fallback. void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU); +Optional ConstantFoldBinOp(unsigned Opcode, const unsigned Op1, + const unsigned Op2, + const MachineRegisterInfo &MRI); } // End namespace llvm. #endif diff --git a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h index 80bd796d537..9c918ae1104 100644 --- a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -70,7 +70,7 @@ namespace ISD { /// of the frame or return address to return. An index of zero corresponds /// to the current function's frame or return address, an index of one to /// the parent's frame or return address, and so on. - FRAMEADDR, RETURNADDR, ADDROFRETURNADDR, + FRAMEADDR, RETURNADDR, ADDROFRETURNADDR, SPONENTRY, /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic. /// Materializes the offset from the local object pointer of another @@ -256,6 +256,29 @@ namespace ISD { /// Same for multiplication. SMULO, UMULO, + /// RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 + /// integers with the same bit width (W). If the true value of LHS + RHS + /// exceeds the largest value that can be represented by W bits, the + /// resulting value is this maximum value. Otherwise, if this value is less + /// than the smallest value that can be represented by W bits, the + /// resulting value is this minimum value. + SADDSAT, UADDSAT, + + /// RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 + /// integers with the same bit width (W). If the true value of LHS - RHS + /// exceeds the largest value that can be represented by W bits, the + /// resulting value is this maximum value. Otherwise, if this value is less + /// than the smallest value that can be represented by W bits, the + /// resulting value is this minimum value. + SSUBSAT, USUBSAT, + + /// RESULT = SMULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on + /// 2 integers with the same width and scale. SCALE represents the scale of + /// both operands as fixed point numbers. This SCALE parameter must be a + /// constant integer. A scale of zero is effectively performing + /// multiplication on 2 integers. + SMULFIX, + /// Simple binary floating point operators. FADD, FSUB, FMUL, FDIV, FREM, @@ -272,7 +295,8 @@ namespace ISD { /// They are used to limit optimizations while the DAG is being optimized. STRICT_FSQRT, STRICT_FPOW, STRICT_FPOWI, STRICT_FSIN, STRICT_FCOS, STRICT_FEXP, STRICT_FEXP2, STRICT_FLOG, STRICT_FLOG10, STRICT_FLOG2, - STRICT_FRINT, STRICT_FNEARBYINT, + STRICT_FRINT, STRICT_FNEARBYINT, STRICT_FMAXNUM, STRICT_FMINNUM, + STRICT_FCEIL, STRICT_FFLOOR, STRICT_FROUND, STRICT_FTRUNC, /// FMA - Perform a * b + c with no intermediate rounding step. FMA, @@ -377,9 +401,13 @@ namespace ISD { /// When the 1st operand is a vector, the shift amount must be in the same /// type. (TLI.getShiftAmountTy() will return the same type when the input /// type is a vector.) - /// For rotates, the shift amount is treated as an unsigned amount modulo - /// the element size of the first operand. - SHL, SRA, SRL, ROTL, ROTR, + /// For rotates and funnel shifts, the shift amount is treated as an unsigned + /// amount modulo the element size of the first operand. + /// + /// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount. + /// fshl(X,Y,Z): (X << (Z % BW)) | (Y >> (BW - (Z % BW))) + /// fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW)) + SHL, SRA, SRL, ROTL, ROTR, FSHL, FSHR, /// Byte Swap and Counting operators. BSWAP, CTTZ, CTLZ, CTPOP, BITREVERSE, @@ -461,31 +489,33 @@ namespace ISD { /// in-register any-extension of the low lanes of an integer vector. The /// result type must have fewer elements than the operand type, and those /// elements must be larger integer types such that the total size of the - /// operand type and the result type match. Each of the low operand - /// elements is any-extended into the corresponding, wider result - /// elements with the high bits becoming undef. + /// operand type is less than or equal to the size of the result type. Each + /// of the low operand elements is any-extended into the corresponding, + /// wider result elements with the high bits becoming undef. + /// NOTE: The type legalizer prefers to make the operand and result size + /// the same to allow expansion to shuffle vector during op legalization. ANY_EXTEND_VECTOR_INREG, /// SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an /// in-register sign-extension of the low lanes of an integer vector. The /// result type must have fewer elements than the operand type, and those /// elements must be larger integer types such that the total size of the - /// operand type and the result type match. Each of the low operand - /// elements is sign-extended into the corresponding, wider result - /// elements. - // FIXME: The SIGN_EXTEND_INREG node isn't specifically limited to - // scalars, but it also doesn't handle vectors well. Either it should be - // restricted to scalars or this node (and its handling) should be merged - // into it. + /// operand type is less than or equal to the size of the result type. Each + /// of the low operand elements is sign-extended into the corresponding, + /// wider result elements. + /// NOTE: The type legalizer prefers to make the operand and result size + /// the same to allow expansion to shuffle vector during op legalization. SIGN_EXTEND_VECTOR_INREG, /// ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an /// in-register zero-extension of the low lanes of an integer vector. The /// result type must have fewer elements than the operand type, and those /// elements must be larger integer types such that the total size of the - /// operand type and the result type match. Each of the low operand - /// elements is zero-extended into the corresponding, wider result - /// elements. + /// operand type is less than or equal to the size of the result type. Each + /// of the low operand elements is zero-extended into the corresponding, + /// wider result elements. + /// NOTE: The type legalizer prefers to make the operand and result size + /// the same to allow expansion to shuffle vector during op legalization. ZERO_EXTEND_VECTOR_INREG, /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned @@ -550,22 +580,29 @@ namespace ISD { /// is often a storage-only type but has native conversions. FP16_TO_FP, FP_TO_FP16, - /// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, - /// FLOG, FLOG2, FLOG10, FEXP, FEXP2, - /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR - Perform various unary - /// floating point operations. These are inspired by libm. - FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, + /// Perform various unary floating-point operations inspired by libm. + FNEG, FABS, FSQRT, FCBRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, /// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two /// values. - /// In the case where a single input is NaN, the non-NaN input is returned. + // + /// In the case where a single input is a NaN (either signaling or quiet), + /// the non-NaN input is returned. /// /// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. FMINNUM, FMAXNUM, - /// FMINNAN/FMAXNAN - Behave identically to FMINNUM/FMAXNUM, except that - /// when a single input is NaN, NaN is returned. - FMINNAN, FMAXNAN, + + /// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on + /// two values, following the IEEE-754 2008 definition. This differs from + /// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a + /// signaling NaN, returns a quiet NaN. + FMINNUM_IEEE, FMAXNUM_IEEE, + + /// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 + /// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 + /// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics. + FMINIMUM, FMAXIMUM, /// FSINCOS - Compute both fsin and fcos as a single operation. FSINCOS, @@ -786,11 +823,20 @@ namespace ISD { // Masked load and store - consecutive vector load and store operations // with additional mask operand that prevents memory accesses to the // masked-off lanes. + // + // Val, OutChain = MLOAD(BasePtr, Mask, PassThru) + // OutChain = MSTORE(Value, BasePtr, Mask) MLOAD, MSTORE, // Masked gather and scatter - load and store operations for a vector of // random addresses with additional mask operand that prevents memory // accesses to the masked-off lanes. + // + // Val, OutChain = GATHER(InChain, PassThru, Mask, BasePtr, Index, Scale) + // OutChain = SCATTER(InChain, Value, Mask, BasePtr, Index, Scale) + // + // The Index operand can have more vector elements than the other operands + // due to type legalization. The extra elements are ignored. MGATHER, MSCATTER, /// This corresponds to the llvm.lifetime.* intrinsics. The first operand diff --git a/contrib/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/contrib/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h index c3046da90b8..38fcb37b1e6 100644 --- a/contrib/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ b/contrib/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -15,7 +15,7 @@ #ifndef LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H #define LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H -#include "llvm/CodeGen/GCs.h" +#include "llvm/CodeGen/BuiltinGCs.h" #include namespace { diff --git a/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h b/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h index fee131e4a3c..18c13ca8f59 100644 --- a/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -15,7 +15,7 @@ #ifndef LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H #define LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H -#include "llvm/CodeGen/GCs.h" +#include "llvm/CodeGen/BuiltinGCs.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/Target/TargetMachine.h" @@ -36,11 +36,7 @@ namespace { (void) llvm::createGreedyRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); - llvm::linkCoreCLRGC(); - llvm::linkOcamlGC(); - llvm::linkErlangGC(); - llvm::linkShadowStackGC(); - llvm::linkStatepointExampleGC(); + llvm::linkAllBuiltinGCs(); (void) llvm::createBURRListDAGScheduler(nullptr, llvm::CodeGenOpt::Default); diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h index 291a07a712c..16ab1dc475c 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h @@ -198,10 +198,10 @@ class VirtRegMap; void pruneValue(LiveRange &LR, SlotIndex Kill, SmallVectorImpl *EndPoints); - /// This function should not be used. Its intend is to tell you that - /// you are doing something wrong if you call pruveValue directly on a + /// This function should not be used. Its intent is to tell you that you are + /// doing something wrong if you call pruneValue directly on a /// LiveInterval. Indeed, you are supposed to call pruneValue on the main - /// LiveRange and all the LiveRange of the subranges if any. + /// LiveRange and all the LiveRanges of the subranges if any. LLVM_ATTRIBUTE_UNUSED void pruneValue(LiveInterval &, SlotIndex, SmallVectorImpl *) { llvm_unreachable( diff --git a/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h b/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h index 301a45066b4..7312902e21b 100644 --- a/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h +++ b/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h @@ -48,7 +48,8 @@ class raw_ostream; /// when walking backward/forward through a basic block. class LivePhysRegs { const TargetRegisterInfo *TRI = nullptr; - SparseSet LiveRegs; + using RegisterSet = SparseSet>; + RegisterSet LiveRegs; public: /// Constructs an unitialized set. init() needs to be called to initialize it. @@ -76,7 +77,7 @@ public: bool empty() const { return LiveRegs.empty(); } /// Adds a physical register and all its sub-registers to the set. - void addReg(unsigned Reg) { + void addReg(MCPhysReg Reg) { assert(TRI && "LivePhysRegs is not initialized."); assert(Reg <= TRI->getNumRegs() && "Expected a physical register."); for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); @@ -86,7 +87,7 @@ public: /// Removes a physical register, all its sub-registers, and all its /// super-registers from the set. - void removeReg(unsigned Reg) { + void removeReg(MCPhysReg Reg) { assert(TRI && "LivePhysRegs is not initialized."); assert(Reg <= TRI->getNumRegs() && "Expected a physical register."); for (MCRegAliasIterator R(Reg, TRI, true); R.isValid(); ++R) @@ -95,7 +96,7 @@ public: /// Removes physical registers clobbered by the regmask operand \p MO. void removeRegsInMask(const MachineOperand &MO, - SmallVectorImpl> *Clobbers = + SmallVectorImpl> *Clobbers = nullptr); /// Returns true if register \p Reg is contained in the set. This also @@ -103,10 +104,10 @@ public: /// addReg() always adds all sub-registers to the set as well. /// Note: Returns false if just some sub registers are live, use available() /// when searching a free register. - bool contains(unsigned Reg) const { return LiveRegs.count(Reg); } + bool contains(MCPhysReg Reg) const { return LiveRegs.count(Reg); } /// Returns true if register \p Reg and no aliasing register is in the set. - bool available(const MachineRegisterInfo &MRI, unsigned Reg) const; + bool available(const MachineRegisterInfo &MRI, MCPhysReg Reg) const; /// Remove defined registers and regmask kills from the set. void removeDefs(const MachineInstr &MI); @@ -126,7 +127,7 @@ public: /// defined or clobbered by a regmask. The operand will identify whether this /// is a regmask or register operand. void stepForward(const MachineInstr &MI, - SmallVectorImpl> &Clobbers); + SmallVectorImpl> &Clobbers); /// Adds all live-in registers of basic block \p MBB. /// Live in registers are the registers in the blocks live-in list and the @@ -143,7 +144,7 @@ public: /// registers. void addLiveOutsNoPristines(const MachineBasicBlock &MBB); - using const_iterator = SparseSet::const_iterator; + using const_iterator = RegisterSet::const_iterator; const_iterator begin() const { return LiveRegs.begin(); } const_iterator end() const { return LiveRegs.end(); } diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h index 249545906e0..5e9dd8b3cdf 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h @@ -85,14 +85,14 @@ public: bool empty() const { return Units.none(); } /// Adds register units covered by physical register \p Reg. - void addReg(unsigned Reg) { + void addReg(MCPhysReg Reg) { for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) Units.set(*Unit); } /// Adds register units covered by physical register \p Reg that are /// part of the lanemask \p Mask. - void addRegMasked(unsigned Reg, LaneBitmask Mask) { + void addRegMasked(MCPhysReg Reg, LaneBitmask Mask) { for (MCRegUnitMaskIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) { LaneBitmask UnitMask = (*Unit).second; if (UnitMask.none() || (UnitMask & Mask).any()) @@ -101,7 +101,7 @@ public: } /// Removes all register units covered by physical register \p Reg. - void removeReg(unsigned Reg) { + void removeReg(MCPhysReg Reg) { for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) Units.reset(*Unit); } @@ -115,7 +115,7 @@ public: void addRegsInMask(const uint32_t *RegMask); /// Returns true if no part of physical register \p Reg is live. - bool available(unsigned Reg) const { + bool available(MCPhysReg Reg) const { for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) { if (Units.test(*Unit)) return false; diff --git a/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h index 7f46406c478..98ac81915dc 100644 --- a/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -425,6 +425,7 @@ struct MachineFrameInfo { StringValue StackProtector; // TODO: Serialize FunctionContextIdx unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet. + unsigned CVBytesOfCalleeSavedRegisters = 0; bool HasOpaqueSPAdjustment = false; bool HasVAStart = false; bool HasMustTailInVarArgFunc = false; @@ -443,6 +444,8 @@ struct MachineFrameInfo { AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls && StackProtector == Other.StackProtector && MaxCallFrameSize == Other.MaxCallFrameSize && + CVBytesOfCalleeSavedRegisters == + Other.CVBytesOfCalleeSavedRegisters && HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment && HasVAStart == Other.HasVAStart && HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc && @@ -465,6 +468,8 @@ template <> struct MappingTraits { YamlIO.mapOptional("stackProtector", MFI.StackProtector, StringValue()); // Don't print it out when it's empty. YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0); + YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters", + MFI.CVBytesOfCalleeSavedRegisters, 0U); YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment, false); YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false); @@ -489,6 +494,7 @@ struct MachineFunction { bool FailedISel = false; // Register information bool TracksRegLiveness = false; + bool HasWinCFI = false; std::vector VirtualRegisters; std::vector LiveIns; Optional> CalleeSavedRegisters; @@ -512,6 +518,7 @@ template <> struct MappingTraits { YamlIO.mapOptional("selected", MF.Selected, false); YamlIO.mapOptional("failedISel", MF.FailedISel, false); YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false); + YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false); YamlIO.mapOptional("registers", MF.VirtualRegisters, std::vector()); YamlIO.mapOptional("liveins", MF.LiveIns, diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h index ace33efd871..ec2f270fcb3 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -569,6 +569,12 @@ public: return !empty() && back().isReturn(); } + /// Convenience function that returns true if the bock ends in a EH scope + /// return instruction. + bool isEHScopeReturnBlock() const { + return !empty() && back().isEHScopeReturn(); + } + /// Split the critical edge from this block to the given successor block, and /// return the newly created block, or null if splitting is not possible. /// diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 2d6081f3577..c2706a21a17 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -28,9 +28,14 @@ class AllocaInst; /// The CalleeSavedInfo class tracks the information need to locate where a /// callee saved register is in the current frame. +/// Callee saved reg can also be saved to a different register rather than +/// on the stack by setting DstReg instead of FrameIdx. class CalleeSavedInfo { unsigned Reg; - int FrameIdx; + union { + int FrameIdx; + unsigned DstReg; + }; /// Flag indicating whether the register is actually restored in the epilog. /// In most cases, if a register is saved, it is also restored. There are /// some situations, though, when this is not the case. For example, the @@ -44,17 +49,29 @@ class CalleeSavedInfo { /// by implicit uses on the return instructions, however, the required /// changes in the ARM backend would be quite extensive. bool Restored; + /// Flag indicating whether the register is spilled to stack or another + /// register. + bool SpilledToReg; public: explicit CalleeSavedInfo(unsigned R, int FI = 0) - : Reg(R), FrameIdx(FI), Restored(true) {} + : Reg(R), FrameIdx(FI), Restored(true), SpilledToReg(false) {} // Accessors. unsigned getReg() const { return Reg; } int getFrameIdx() const { return FrameIdx; } - void setFrameIdx(int FI) { FrameIdx = FI; } + unsigned getDstReg() const { return DstReg; } + void setFrameIdx(int FI) { + FrameIdx = FI; + SpilledToReg = false; + } + void setDstReg(unsigned SpillReg) { + DstReg = SpillReg; + SpilledToReg = true; + } bool isRestored() const { return Restored; } void setRestored(bool R) { Restored = R; } + bool isSpilledToReg() const { return SpilledToReg; } }; /// The MachineFrameInfo class represents an abstract stack frame until @@ -266,10 +283,14 @@ private: /// It is only valid during and after prolog/epilog code insertion. unsigned MaxCallFrameSize = ~0u; + /// The number of bytes of callee saved registers that the target wants to + /// report for the current function in the CodeView S_FRAMEPROC record. + unsigned CVBytesOfCalleeSavedRegisters = 0; + /// The prolog/epilog code inserter fills in this vector with each - /// callee saved register saved in the frame. Beyond its use by the prolog/ - /// epilog code inserter, this data used for debug info and exception - /// handling. + /// callee saved register saved in either the frame or a different + /// register. Beyond its use by the prolog/ epilog code inserter, + /// this data is used for debug info and exception handling. std::vector CSInfo; /// Has CSInfo been set yet? @@ -603,6 +624,15 @@ public: } void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } + /// Returns how many bytes of callee-saved registers the target pushed in the + /// prologue. Only used for debug info. + unsigned getCVBytesOfCalleeSavedRegisters() const { + return CVBytesOfCalleeSavedRegisters; + } + void setCVBytesOfCalleeSavedRegisters(unsigned S) { + CVBytesOfCalleeSavedRegisters = S; + } + /// Create a new object at a fixed location on the stack. /// All fixed objects should be created before other objects are created for /// efficiency. By default, fixed objects are not pointed to by LLVM IR diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h index e8a4d529faa..25edf5bcce5 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h @@ -58,6 +58,7 @@ class DILocalVariable; class DILocation; class Function; class GlobalValue; +class LLVMTargetMachine; class MachineConstantPool; class MachineFrameInfo; class MachineFunction; @@ -70,7 +71,6 @@ class Pass; class PseudoSourceValueManager; class raw_ostream; class SlotIndexes; -class TargetMachine; class TargetRegisterClass; class TargetSubtargetInfo; struct WasmEHFuncInfo; @@ -225,7 +225,7 @@ struct LandingPadInfo { class MachineFunction { const Function &F; - const TargetMachine &Target; + const LLVMTargetMachine &Target; const TargetSubtargetInfo *STI; MCContext &Ctx; MachineModuleInfo &MMI; @@ -294,7 +294,7 @@ class MachineFunction { bool HasInlineAsm = false; /// True if any WinCFI instruction have been emitted in this function. - Optional HasWinCFI; + bool HasWinCFI = false; /// Current high-level properties of the IR of the function (e.g. is in SSA /// form or whether registers have been allocated) @@ -316,6 +316,9 @@ class MachineFunction { /// Map a landing pad's EH symbol to the call site indexes. DenseMap> LPadToCallSiteMap; + /// Map a landing pad to its index. + DenseMap WasmLPadToIndexMap; + /// Map of invoke call site index values to associated begin EH_LABEL. DenseMap CallSiteMap; @@ -363,10 +366,31 @@ public: int Slot, const DILocation *Loc) : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; + + class Delegate { + virtual void anchor(); + + public: + virtual ~Delegate() = default; + /// Callback after an insertion. This should not modify the MI directly. + virtual void MF_HandleInsertion(MachineInstr &MI) = 0; + /// Callback before a removal. This should not modify the MI directly. + virtual void MF_HandleRemoval(MachineInstr &MI) = 0; + }; + +private: + Delegate *TheDelegate = nullptr; + + // Callbacks for insertion and removal. + void handleInsertion(MachineInstr &MI); + void handleRemoval(MachineInstr &MI); + friend struct ilist_traits; + +public: using VariableDbgInfoMapTy = SmallVector; VariableDbgInfoMapTy VariableDbgInfos; - MachineFunction(const Function &F, const TargetMachine &Target, + MachineFunction(const Function &F, const LLVMTargetMachine &Target, const TargetSubtargetInfo &STI, unsigned FunctionNum, MachineModuleInfo &MMI); MachineFunction(const MachineFunction &) = delete; @@ -379,6 +403,23 @@ public: init(); } + /// Reset the currently registered delegate - otherwise assert. + void resetDelegate(Delegate *delegate) { + assert(TheDelegate == delegate && + "Only the current delegate can perform reset!"); + TheDelegate = nullptr; + } + + /// Set the delegate. resetDelegate must be called before attempting + /// to set. + void setDelegate(Delegate *delegate) { + assert(delegate && !TheDelegate && + "Attempted to set delegate to null, or to change it without " + "first resetting it!"); + + TheDelegate = delegate; + } + MachineModuleInfo &getMMI() const { return MMI; } MCContext &getContext() const { return Ctx; } @@ -397,7 +438,7 @@ public: unsigned getFunctionNumber() const { return FunctionNumber; } /// getTarget - Return the target machine this machine code is compiled with - const TargetMachine &getTarget() const { return Target; } + const LLVMTargetMachine &getTarget() const { return Target; } /// getSubtarget - Return the subtarget for which this machine code is being /// compiled. @@ -484,8 +525,7 @@ public: } bool hasWinCFI() const { - assert(HasWinCFI.hasValue() && "HasWinCFI not set yet!"); - return *HasWinCFI; + return HasWinCFI; } void setHasWinCFI(bool v) { HasWinCFI = v; } @@ -619,6 +659,14 @@ public: BasicBlocks.sort(comp); } + /// Return the number of \p MachineInstrs in this \p MachineFunction. + unsigned getInstructionCount() const { + unsigned InstrCount = 0; + for (const MachineBasicBlock &MBB : BasicBlocks) + InstrCount += MBB.size(); + return InstrCount; + } + //===--------------------------------------------------------------------===// // Internal functions used to automatically number MachineBasicBlocks @@ -711,23 +759,14 @@ public: /// Allocate and initialize a register mask with @p NumRegister bits. uint32_t *allocateRegMask(); - /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand - /// pointers. This array is owned by the MachineFunction. - MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num); - - /// extractLoadMemRefs - Allocate an array and populate it with just the - /// load information from the given MachineMemOperand sequence. - std::pair - extractLoadMemRefs(MachineInstr::mmo_iterator Begin, - MachineInstr::mmo_iterator End); - - /// extractStoreMemRefs - Allocate an array and populate it with just the - /// store information from the given MachineMemOperand sequence. - std::pair - extractStoreMemRefs(MachineInstr::mmo_iterator Begin, - MachineInstr::mmo_iterator End); + /// Allocate and construct an extra info structure for a `MachineInstr`. + /// + /// This is allocated on the function's allocator and so lives the life of + /// the function. + MachineInstr::ExtraInfo * + createMIExtraInfo(ArrayRef MMOs, + MCSymbol *PreInstrSymbol = nullptr, + MCSymbol *PostInstrSymbol = nullptr); /// Allocate a string and populate it with the given external symbol name. const char *createExternalSymbolName(StringRef Name); @@ -776,7 +815,8 @@ public: LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad); /// Remap landing pad labels and remove any deleted landing pads. - void tidyLandingPads(DenseMap *LPMap = nullptr); + void tidyLandingPads(DenseMap *LPMap = nullptr, + bool TidyIfNoBeginLabels = true); /// Return a reference to the landing pad info for the current function. const std::vector &getLandingPads() const { @@ -788,7 +828,9 @@ public: void addInvoke(MachineBasicBlock *LandingPad, MCSymbol *BeginLabel, MCSymbol *EndLabel); - /// Add a new panding pad. Returns the label ID for the landing pad entry. + /// Add a new panding pad, and extract the exception handling information from + /// the landingpad instruction. Returns the label ID for the landing pad + /// entry. MCSymbol *addLandingPad(MachineBasicBlock *LandingPad); /// Provide the catch typeinfo for a landing pad. @@ -817,6 +859,22 @@ public: /// Map the landing pad's EH symbol to the call site indexes. void setCallSiteLandingPad(MCSymbol *Sym, ArrayRef Sites); + /// Map the landing pad to its index. Used for Wasm exception handling. + void setWasmLandingPadIndex(const MachineBasicBlock *LPad, unsigned Index) { + WasmLPadToIndexMap[LPad] = Index; + } + + /// Returns true if the landing pad has an associate index in wasm EH. + bool hasWasmLandingPadIndex(const MachineBasicBlock *LPad) const { + return WasmLPadToIndexMap.count(LPad); + } + + /// Get the index in wasm EH for a given landing pad. + unsigned getWasmLandingPadIndex(const MachineBasicBlock *LPad) const { + assert(hasWasmLandingPadIndex(LPad)); + return WasmLPadToIndexMap.lookup(LPad); + } + /// Get the call site indexes for a landing pad EH symbol. SmallVectorImpl &getCallSiteLandingPad(MCSymbol *Sym) { assert(hasCallSiteLandingPad(Sym) && @@ -880,15 +938,6 @@ public: } }; -/// \name Exception Handling -/// \{ - -/// Extract the exception handling information from the landingpad instruction -/// and add them to the specified machine module info. -void addLandingPadInfo(const LandingPadInst &I, MachineBasicBlock &MBB); - -/// \} - //===--------------------------------------------------------------------===// // GraphTraits specializations for function basic block graphs (CFGs) //===--------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h index 88e13cdf413..ea1a2a536fc 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h @@ -17,16 +17,20 @@ #define LLVM_CODEGEN_MACHINEINSTR_H #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerSumType.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/InlineAsm.h" #include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/ArrayRecycler.h" +#include "llvm/Support/TrailingObjects.h" #include #include #include @@ -61,7 +65,7 @@ class MachineInstr : public ilist_node_with_parent> { public: - using mmo_iterator = MachineMemOperand **; + using mmo_iterator = ArrayRef::iterator; /// Flags to specify different kinds of comments to output in /// assembly code. These flags carry semantic information not @@ -93,8 +97,14 @@ public: // contraction operations like fma. FmAfn = 1 << 9, // Instruction may map to Fast math // instrinsic approximation. - FmReassoc = 1 << 10 // Instruction supports Fast math + FmReassoc = 1 << 10, // Instruction supports Fast math // reassociation of operand order. + NoUWrap = 1 << 11, // Instruction supports binary operator + // no unsigned wrap. + NoSWrap = 1 << 12, // Instruction supports binary operator + // no signed wrap. + IsExact = 1 << 13 // Instruction supports division is + // known to be exact. }; private: @@ -118,14 +128,102 @@ private: // anything other than to convey comment // information to AsmPrinter. - uint8_t NumMemRefs = 0; // Information on memory references. - // Note that MemRefs == nullptr, means 'don't know', not 'no memory access'. - // Calling code must treat missing information conservatively. If the number - // of memory operands required to be precise exceeds the maximum value of - // NumMemRefs - currently 256 - we remove the operands entirely. Note also - // that this is a non-owning reference to a shared copy on write buffer owned - // by the MachineFunction and created via MF.allocateMemRefsArray. - mmo_iterator MemRefs = nullptr; + /// Internal implementation detail class that provides out-of-line storage for + /// extra info used by the machine instruction when this info cannot be stored + /// in-line within the instruction itself. + /// + /// This has to be defined eagerly due to the implementation constraints of + /// `PointerSumType` where it is used. + class ExtraInfo final + : TrailingObjects { + public: + static ExtraInfo *create(BumpPtrAllocator &Allocator, + ArrayRef MMOs, + MCSymbol *PreInstrSymbol = nullptr, + MCSymbol *PostInstrSymbol = nullptr) { + bool HasPreInstrSymbol = PreInstrSymbol != nullptr; + bool HasPostInstrSymbol = PostInstrSymbol != nullptr; + auto *Result = new (Allocator.Allocate( + totalSizeToAlloc( + MMOs.size(), HasPreInstrSymbol + HasPostInstrSymbol), + alignof(ExtraInfo))) + ExtraInfo(MMOs.size(), HasPreInstrSymbol, HasPostInstrSymbol); + + // Copy the actual data into the trailing objects. + std::copy(MMOs.begin(), MMOs.end(), + Result->getTrailingObjects()); + + if (HasPreInstrSymbol) + Result->getTrailingObjects()[0] = PreInstrSymbol; + if (HasPostInstrSymbol) + Result->getTrailingObjects()[HasPreInstrSymbol] = + PostInstrSymbol; + + return Result; + } + + ArrayRef getMMOs() const { + return makeArrayRef(getTrailingObjects(), NumMMOs); + } + + MCSymbol *getPreInstrSymbol() const { + return HasPreInstrSymbol ? getTrailingObjects()[0] : nullptr; + } + + MCSymbol *getPostInstrSymbol() const { + return HasPostInstrSymbol + ? getTrailingObjects()[HasPreInstrSymbol] + : nullptr; + } + + private: + friend TrailingObjects; + + // Description of the extra info, used to interpret the actual optional + // data appended. + // + // Note that this is not terribly space optimized. This leaves a great deal + // of flexibility to fit more in here later. + const int NumMMOs; + const bool HasPreInstrSymbol; + const bool HasPostInstrSymbol; + + // Implement the `TrailingObjects` internal API. + size_t numTrailingObjects(OverloadToken) const { + return NumMMOs; + } + size_t numTrailingObjects(OverloadToken) const { + return HasPreInstrSymbol + HasPostInstrSymbol; + } + + // Just a boring constructor to allow us to initialize the sizes. Always use + // the `create` routine above. + ExtraInfo(int NumMMOs, bool HasPreInstrSymbol, bool HasPostInstrSymbol) + : NumMMOs(NumMMOs), HasPreInstrSymbol(HasPreInstrSymbol), + HasPostInstrSymbol(HasPostInstrSymbol) {} + }; + + /// Enumeration of the kinds of inline extra info available. It is important + /// that the `MachineMemOperand` inline kind has a tag value of zero to make + /// it accessible as an `ArrayRef`. + enum ExtraInfoInlineKinds { + EIIK_MMO = 0, + EIIK_PreInstrSymbol, + EIIK_PostInstrSymbol, + EIIK_OutOfLine + }; + + // We store extra information about the instruction here. The common case is + // expected to be nothing or a single pointer (typically a MMO or a symbol). + // We work to optimize this common case by storing it inline here rather than + // requiring a separate allocation, but we fall back to an allocation when + // multiple pointers are needed. + PointerSumType, + PointerSumTypeMember, + PointerSumTypeMember, + PointerSumTypeMember> + Info; DebugLoc debugLoc; // Source line information. @@ -310,7 +408,7 @@ public: /// Returns the opcode of this MachineInstr. unsigned getOpcode() const { return MCID->Opcode; } - /// Access to explicit operands of the instruction. + /// Retuns the total number of operands. unsigned getNumOperands() const { return NumOperands; } const MachineOperand& getOperand(unsigned i) const { @@ -412,28 +510,70 @@ public: return I - operands_begin(); } - /// Access to memory operands of the instruction - mmo_iterator memoperands_begin() const { return MemRefs; } - mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; } + /// Access to memory operands of the instruction. If there are none, that does + /// not imply anything about whether the function accesses memory. Instead, + /// the caller must behave conservatively. + ArrayRef memoperands() const { + if (!Info) + return {}; + + if (Info.is()) + return makeArrayRef(Info.getAddrOfZeroTagPointer(), 1); + + if (ExtraInfo *EI = Info.get()) + return EI->getMMOs(); + + return {}; + } + + /// Access to memory operands of the instruction. + /// + /// If `memoperands_begin() == memoperands_end()`, that does not imply + /// anything about whether the function accesses memory. Instead, the caller + /// must behave conservatively. + mmo_iterator memoperands_begin() const { return memoperands().begin(); } + + /// Access to memory operands of the instruction. + /// + /// If `memoperands_begin() == memoperands_end()`, that does not imply + /// anything about whether the function accesses memory. Instead, the caller + /// must behave conservatively. + mmo_iterator memoperands_end() const { return memoperands().end(); } + /// Return true if we don't have any memory operands which described the /// memory access done by this instruction. If this is true, calling code /// must be conservative. - bool memoperands_empty() const { return NumMemRefs == 0; } - - iterator_range memoperands() { - return make_range(memoperands_begin(), memoperands_end()); - } - iterator_range memoperands() const { - return make_range(memoperands_begin(), memoperands_end()); - } + bool memoperands_empty() const { return memoperands().empty(); } /// Return true if this instruction has exactly one MachineMemOperand. - bool hasOneMemOperand() const { - return NumMemRefs == 1; - } + bool hasOneMemOperand() const { return memoperands().size() == 1; } /// Return the number of memory operands. - unsigned getNumMemOperands() const { return NumMemRefs; } + unsigned getNumMemOperands() const { return memoperands().size(); } + + /// Helper to extract a pre-instruction symbol if one has been added. + MCSymbol *getPreInstrSymbol() const { + if (!Info) + return nullptr; + if (MCSymbol *S = Info.get()) + return S; + if (ExtraInfo *EI = Info.get()) + return EI->getPreInstrSymbol(); + + return nullptr; + } + + /// Helper to extract a post-instruction symbol if one has been added. + MCSymbol *getPostInstrSymbol() const { + if (!Info) + return nullptr; + if (MCSymbol *S = Info.get()) + return S; + if (ExtraInfo *EI = Info.get()) + return EI->getPostInstrSymbol(); + + return nullptr; + } /// API for querying MachineInstr properties. They are the same as MCInstrDesc /// queries but they are bundle aware. @@ -450,6 +590,8 @@ public: /// The second argument indicates whether the query should look inside /// instruction bundles. bool hasProperty(unsigned MCFlag, QueryType Type = AnyInBundle) const { + assert(MCFlag < 64 && + "MCFlag out of range for bit mask in getFlags/hasPropertyInBundle."); // Inline the fast path for unbundled or bundle-internal instructions. if (Type == IgnoreBundle || !isBundled() || isBundledWithPred()) return getDesc().getFlags() & (1ULL << MCFlag); @@ -482,6 +624,12 @@ public: return hasProperty(MCID::Return, Type); } + /// Return true if this is an instruction that marks the end of an EH scope, + /// i.e., a catchpad or a cleanuppad instruction. + bool isEHScopeReturn(QueryType Type = AnyInBundle) const { + return hasProperty(MCID::EHScopeReturn, Type); + } + bool isCall(QueryType Type = AnyInBundle) const { return hasProperty(MCID::Call, Type); } @@ -1323,47 +1471,63 @@ public: /// fewer operand than it started with. void RemoveOperand(unsigned OpNo); + /// Clear this MachineInstr's memory reference descriptor list. This resets + /// the memrefs to their most conservative state. This should be used only + /// as a last resort since it greatly pessimizes our knowledge of the memory + /// access performed by the instruction. + void dropMemRefs(MachineFunction &MF); + + /// Assign this MachineInstr's memory reference descriptor list. + /// + /// Unlike other methods, this *will* allocate them into a new array + /// associated with the provided `MachineFunction`. + void setMemRefs(MachineFunction &MF, ArrayRef MemRefs); + /// Add a MachineMemOperand to the machine instruction. /// This function should be used only occasionally. The setMemRefs function /// is the primary method for setting up a MachineInstr's MemRefs list. void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); - /// Assign this MachineInstr's memory reference descriptor list. - /// This does not transfer ownership. - void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { - setMemRefs(std::make_pair(NewMemRefs, NewMemRefsEnd-NewMemRefs)); - } + /// Clone another MachineInstr's memory reference descriptor list and replace + /// ours with it. + /// + /// Note that `*this` may be the incoming MI! + /// + /// Prefer this API whenever possible as it can avoid allocations in common + /// cases. + void cloneMemRefs(MachineFunction &MF, const MachineInstr &MI); - /// Assign this MachineInstr's memory reference descriptor list. First - /// element in the pair is the begin iterator/pointer to the array; the - /// second is the number of MemoryOperands. This does not transfer ownership - /// of the underlying memory. - void setMemRefs(std::pair NewMemRefs) { - MemRefs = NewMemRefs.first; - NumMemRefs = uint8_t(NewMemRefs.second); - assert(NumMemRefs == NewMemRefs.second && - "Too many memrefs - must drop memory operands"); - } + /// Clone the merge of multiple MachineInstrs' memory reference descriptors + /// list and replace ours with it. + /// + /// Note that `*this` may be one of the incoming MIs! + /// + /// Prefer this API whenever possible as it can avoid allocations in common + /// cases. + void cloneMergedMemRefs(MachineFunction &MF, + ArrayRef MIs); - /// Return a set of memrefs (begin iterator, size) which conservatively - /// describe the memory behavior of both MachineInstrs. This is appropriate - /// for use when merging two MachineInstrs into one. This routine does not - /// modify the memrefs of the this MachineInstr. - std::pair mergeMemRefsWith(const MachineInstr& Other); + /// Set a symbol that will be emitted just prior to the instruction itself. + /// + /// Setting this to a null pointer will remove any such symbol. + /// + /// FIXME: This is not fully implemented yet. + void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol); + + /// Set a symbol that will be emitted just after the instruction itself. + /// + /// Setting this to a null pointer will remove any such symbol. + /// + /// FIXME: This is not fully implemented yet. + void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol); /// Return the MIFlags which represent both MachineInstrs. This /// should be used when merging two MachineInstrs into one. This routine does /// not modify the MIFlags of this MachineInstr. uint16_t mergeFlagsWith(const MachineInstr& Other) const; - /// Clear this MachineInstr's memory reference descriptor list. This resets - /// the memrefs to their most conservative state. This should be used only - /// as a last resort since it greatly pessimizes our knowledge of the memory - /// access performed by the instruction. - void dropMemRefs() { - MemRefs = nullptr; - NumMemRefs = 0; - } + /// Copy all flags to MachineInst MIFlags + void copyIRFlags(const Instruction &I); /// Break any tie involving OpIdx. void untieRegOperand(unsigned OpIdx) { @@ -1377,6 +1541,13 @@ public: /// Add all implicit def and use operands to this instruction. void addImplicitDefUseOperands(MachineFunction &MF); + /// Scan instructions following MI and collect any matching DBG_VALUEs. + void collectDebugValues(SmallVectorImpl &DbgValues); + + /// Find all DBG_VALUEs immediately following this instruction that point + /// to a register def in this instruction and point them to \p Reg instead. + void changeDebugValuesDefReg(unsigned Reg); + private: /// If this instruction is embedded into a MachineFunction, return the /// MachineRegisterInfo object for the current function, otherwise @@ -1394,7 +1565,7 @@ private: void AddRegOperandsToUseLists(MachineRegisterInfo&); /// Slow path for hasProperty when we're dealing with a bundle. - bool hasPropertyInBundle(unsigned Mask, QueryType Type) const; + bool hasPropertyInBundle(uint64_t Mask, QueryType Type) const; /// Implements the logic of getRegClassConstraintEffectForVReg for the /// this MI and the given operand index \p OpIdx. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index 66560875574..b5e523f655e 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -191,15 +191,20 @@ public: return *this; } - const MachineInstrBuilder &setMemRefs(MachineInstr::mmo_iterator b, - MachineInstr::mmo_iterator e) const { - MI->setMemRefs(b, e); + const MachineInstrBuilder & + setMemRefs(ArrayRef MMOs) const { + MI->setMemRefs(*MF, MMOs); return *this; } - const MachineInstrBuilder &setMemRefs(std::pair MemOperandsRef) const { - MI->setMemRefs(MemOperandsRef); + const MachineInstrBuilder &cloneMemRefs(const MachineInstr &OtherMI) const { + MI->cloneMemRefs(*MF, OtherMI); + return *this; + } + + const MachineInstrBuilder & + cloneMergedMemRefs(ArrayRef OtherMIs) const { + MI->cloneMergedMemRefs(*MF, OtherMIs); return *this; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h index 554e89019b7..4371420bc7a 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -46,10 +46,10 @@ namespace llvm { class BasicBlock; class CallInst; class Function; -class MachineFunction; +class LLVMTargetMachine; class MMIAddrLabelMap; +class MachineFunction; class Module; -class TargetMachine; //===----------------------------------------------------------------------===// /// This class can be derived from and used by targets to hold private @@ -76,7 +76,7 @@ protected: /// for specific use. /// class MachineModuleInfo : public ImmutablePass { - const TargetMachine &TM; + const LLVMTargetMachine &TM; /// This is the MCContext used for the entire code generator. MCContext Context; @@ -145,7 +145,7 @@ class MachineModuleInfo : public ImmutablePass { public: static char ID; // Pass identification, replacement for typeid - explicit MachineModuleInfo(const TargetMachine *TM = nullptr); + explicit MachineModuleInfo(const LLVMTargetMachine *TM = nullptr); ~MachineModuleInfo() override; // Initialization and Finalization diff --git a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h index 6a87fa2fbf0..17df1fa792b 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -80,6 +80,28 @@ public: SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } }; +/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation +/// for COFF targets. +class MachineModuleInfoCOFF : public MachineModuleInfoImpl { + /// GVStubs - These stubs are used to materialize global addresses in PIC + /// mode. + DenseMap GVStubs; + + virtual void anchor(); // Out of line virtual method. + +public: + MachineModuleInfoCOFF(const MachineModuleInfo &) {} + + StubValueTy &getGVStubEntry(MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return GVStubs[Sym]; + } + + /// Accessor methods to return the set of stubs in sorted order. + + SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } +}; + } // end namespace llvm #endif // LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h b/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h index 95bfc24b57f..bfd1e994053 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h @@ -61,9 +61,6 @@ public: /// \p OutlinedFunctions. unsigned FunctionIdx; - /// Set to false if the candidate overlapped with another candidate. - bool InCandidateList = true; - /// Identifier denoting the instructions to emit to call an outlined function /// from this point. Defined by the target. unsigned CallConstructionID; @@ -82,6 +79,12 @@ public: /// been used across the sequence. LiveRegUnits UsedInSequence; + /// Target-specific flags for this Candidate's MBB. + unsigned Flags = 0x0; + + /// True if initLRU has been called on this Candidate. + bool LRUWasSet = false; + /// Return the number of instructions in this Candidate. unsigned getLength() const { return Len; } @@ -99,9 +102,7 @@ public: } /// Returns the call overhead of this candidate if it is in the list. - unsigned getCallOverhead() const { - return InCandidateList ? CallOverhead : 0; - } + unsigned getCallOverhead() const { return CallOverhead; } MachineBasicBlock::iterator &front() { return FirstInst; } MachineBasicBlock::iterator &back() { return LastInst; } @@ -120,9 +121,9 @@ public: Candidate(unsigned StartIdx, unsigned Len, MachineBasicBlock::iterator &FirstInst, MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB, - unsigned FunctionIdx) + unsigned FunctionIdx, unsigned Flags) : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst), - MBB(MBB), FunctionIdx(FunctionIdx) {} + MBB(MBB), FunctionIdx(FunctionIdx), Flags(Flags) {} Candidate() {} /// Used to ensure that \p Candidates are outlined in an order that @@ -138,6 +139,10 @@ public: void initLRU(const TargetRegisterInfo &TRI) { assert(MBB->getParent()->getRegInfo().tracksLiveness() && "Candidate's Machine Function must track liveness"); + // Only initialize once. + if (LRUWasSet) + return; + LRUWasSet = true; LRU.init(TRI); LRU.addLiveOuts(*MBB); @@ -158,24 +163,13 @@ public: /// class of candidate. struct OutlinedFunction { -private: - /// The number of candidates for this \p OutlinedFunction. - unsigned OccurrenceCount = 0; - public: - std::vector> Candidates; + std::vector Candidates; /// The actual outlined function created. /// This is initialized after we go through and create the actual function. MachineFunction *MF = nullptr; - /// A number assigned to this function which appears at the end of its name. - unsigned Name; - - /// The sequence of integers corresponding to the instructions in this - /// function. - std::vector Sequence; - /// Represents the size of a sequence in bytes. (Some instructions vary /// widely in size, so just counting the instructions isn't very useful.) unsigned SequenceSize; @@ -187,49 +181,41 @@ public: unsigned FrameConstructionID; /// Return the number of candidates for this \p OutlinedFunction. - unsigned getOccurrenceCount() { return OccurrenceCount; } - - /// Decrement the occurrence count of this OutlinedFunction and return the - /// new count. - unsigned decrement() { - assert(OccurrenceCount > 0 && "Can't decrement an empty function!"); - OccurrenceCount--; - return getOccurrenceCount(); - } + unsigned getOccurrenceCount() const { return Candidates.size(); } /// Return the number of bytes it would take to outline this /// function. - unsigned getOutliningCost() { + unsigned getOutliningCost() const { unsigned CallOverhead = 0; - for (std::shared_ptr &C : Candidates) - CallOverhead += C->getCallOverhead(); + for (const Candidate &C : Candidates) + CallOverhead += C.getCallOverhead(); return CallOverhead + SequenceSize + FrameOverhead; } /// Return the size in bytes of the unoutlined sequences. - unsigned getNotOutlinedCost() { return OccurrenceCount * SequenceSize; } + unsigned getNotOutlinedCost() const { + return getOccurrenceCount() * SequenceSize; + } /// Return the number of instructions that would be saved by outlining /// this function. - unsigned getBenefit() { + unsigned getBenefit() const { unsigned NotOutlinedCost = getNotOutlinedCost(); unsigned OutlinedCost = getOutliningCost(); return (NotOutlinedCost < OutlinedCost) ? 0 : NotOutlinedCost - OutlinedCost; } - OutlinedFunction(std::vector &Cands, - unsigned SequenceSize, unsigned FrameOverhead, - unsigned FrameConstructionID) - : SequenceSize(SequenceSize), FrameOverhead(FrameOverhead), - FrameConstructionID(FrameConstructionID) { - OccurrenceCount = Cands.size(); - for (Candidate &C : Cands) - Candidates.push_back(std::make_shared(C)); + /// Return the number of instructions in this sequence. + unsigned getNumInstrs() const { return Candidates[0].getLength(); } - unsigned B = getBenefit(); - for (std::shared_ptr &C : Candidates) - C->Benefit = B; + OutlinedFunction(std::vector &Candidates, unsigned SequenceSize, + unsigned FrameOverhead, unsigned FrameConstructionID) + : Candidates(Candidates), SequenceSize(SequenceSize), + FrameOverhead(FrameOverhead), FrameConstructionID(FrameConstructionID) { + const unsigned B = getBenefit(); + for (Candidate &C : Candidates) + C.Benefit = B; } OutlinedFunction() {} diff --git a/contrib/llvm/include/llvm/CodeGen/MachinePassRegistry.h b/contrib/llvm/include/llvm/CodeGen/MachinePassRegistry.h index 3aba0bba7d1..a031c92d914 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachinePassRegistry.h +++ b/contrib/llvm/include/llvm/CodeGen/MachinePassRegistry.h @@ -24,22 +24,20 @@ namespace llvm { -using MachinePassCtor = void *(*)(); - //===----------------------------------------------------------------------===// /// /// MachinePassRegistryListener - Listener to adds and removals of nodes in /// registration list. /// //===----------------------------------------------------------------------===// -class MachinePassRegistryListener { - virtual void anchor(); +template class MachinePassRegistryListener { + virtual void anchor() {} public: MachinePassRegistryListener() = default; virtual ~MachinePassRegistryListener() = default; - virtual void NotifyAdd(StringRef N, MachinePassCtor C, StringRef D) = 0; + virtual void NotifyAdd(StringRef N, PassCtorTy C, StringRef D) = 0; virtual void NotifyRemove(StringRef N) = 0; }; @@ -48,15 +46,15 @@ public: /// MachinePassRegistryNode - Machine pass node stored in registration list. /// //===----------------------------------------------------------------------===// -class MachinePassRegistryNode { +template class MachinePassRegistryNode { private: MachinePassRegistryNode *Next = nullptr; // Next function pass in list. StringRef Name; // Name of function pass. StringRef Description; // Description string. - MachinePassCtor Ctor; // Function pass creator. + PassCtorTy Ctor; // Pass creator. public: - MachinePassRegistryNode(const char *N, const char *D, MachinePassCtor C) + MachinePassRegistryNode(const char *N, const char *D, PassCtorTy C) : Name(N), Description(D), Ctor(C) {} // Accessors @@ -64,7 +62,7 @@ public: MachinePassRegistryNode **getNextAddress() { return &Next; } StringRef getName() const { return Name; } StringRef getDescription() const { return Description; } - MachinePassCtor getCtor() const { return Ctor; } + PassCtorTy getCtor() const { return Ctor; } void setNext(MachinePassRegistryNode *N) { Next = N; } }; @@ -73,11 +71,12 @@ public: /// MachinePassRegistry - Track the registration of machine passes. /// //===----------------------------------------------------------------------===// -class MachinePassRegistry { +template class MachinePassRegistry { private: - MachinePassRegistryNode *List; // List of registry nodes. - MachinePassCtor Default; // Default function pass creator. - MachinePassRegistryListener *Listener; // Listener for list adds are removes. + MachinePassRegistryNode *List; // List of registry nodes. + PassCtorTy Default; // Default function pass creator. + MachinePassRegistryListener + *Listener; // Listener for list adds are removes. public: // NO CONSTRUCTOR - we don't want static constructor ordering to mess @@ -85,19 +84,47 @@ public: // Accessors. // - MachinePassRegistryNode *getList() { return List; } - MachinePassCtor getDefault() { return Default; } - void setDefault(MachinePassCtor C) { Default = C; } - void setDefault(StringRef Name); - void setListener(MachinePassRegistryListener *L) { Listener = L; } + MachinePassRegistryNode *getList() { return List; } + PassCtorTy getDefault() { return Default; } + void setDefault(PassCtorTy C) { Default = C; } + /// setDefault - Set the default constructor by name. + void setDefault(StringRef Name) { + PassCtorTy Ctor = nullptr; + for (MachinePassRegistryNode *R = getList(); R; + R = R->getNext()) { + if (R->getName() == Name) { + Ctor = R->getCtor(); + break; + } + } + assert(Ctor && "Unregistered pass name"); + setDefault(Ctor); + } + void setListener(MachinePassRegistryListener *L) { Listener = L; } /// Add - Adds a function pass to the registration list. /// - void Add(MachinePassRegistryNode *Node); + void Add(MachinePassRegistryNode *Node) { + Node->setNext(List); + List = Node; + if (Listener) + Listener->NotifyAdd(Node->getName(), Node->getCtor(), + Node->getDescription()); + } /// Remove - Removes a function pass from the registration list. /// - void Remove(MachinePassRegistryNode *Node); + void Remove(MachinePassRegistryNode *Node) { + for (MachinePassRegistryNode **I = &List; *I; + I = (*I)->getNextAddress()) { + if (*I == Node) { + if (Listener) + Listener->NotifyRemove(Node->getName()); + *I = (*I)->getNext(); + break; + } + } + } }; //===----------------------------------------------------------------------===// @@ -105,9 +132,11 @@ public: /// RegisterPassParser class - Handle the addition of new machine passes. /// //===----------------------------------------------------------------------===// -template -class RegisterPassParser : public MachinePassRegistryListener, - public cl::parser { +template +class RegisterPassParser + : public MachinePassRegistryListener< + typename RegistryClass::FunctionPassCtor>, + public cl::parser { public: RegisterPassParser(cl::Option &O) : cl::parser(O) {} @@ -129,8 +158,9 @@ public: } // Implement the MachinePassRegistryListener callbacks. - void NotifyAdd(StringRef N, MachinePassCtor C, StringRef D) override { - this->addLiteralOption(N, (typename RegistryClass::FunctionPassCtor)C, D); + void NotifyAdd(StringRef N, typename RegistryClass::FunctionPassCtor C, + StringRef D) override { + this->addLiteralOption(N, C, D); } void NotifyRemove(StringRef N) override { this->removeLiteralOption(N); diff --git a/contrib/llvm/include/llvm/CodeGen/MachinePipeliner.h b/contrib/llvm/include/llvm/CodeGen/MachinePipeliner.h new file mode 100644 index 00000000000..38cb33e90e6 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/MachinePipeliner.h @@ -0,0 +1,608 @@ +//===- MachinePipeliner.h - Machine Software Pipeliner Pass -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// An implementation of the Swing Modulo Scheduling (SMS) software pipeliner. +// +// Software pipelining (SWP) is an instruction scheduling technique for loops +// that overlap loop iterations and exploits ILP via a compiler transformation. +// +// Swing Modulo Scheduling is an implementation of software pipelining +// that generates schedules that are near optimal in terms of initiation +// interval, register requirements, and stage count. See the papers: +// +// "Swing Modulo Scheduling: A Lifetime-Sensitive Approach", by J. Llosa, +// A. Gonzalez, E. Ayguade, and M. Valero. In PACT '96 Proceedings of the 1996 +// Conference on Parallel Architectures and Compilation Techiniques. +// +// "Lifetime-Sensitive Modulo Scheduling in a Production Environment", by J. +// Llosa, E. Ayguade, A. Gonzalez, M. Valero, and J. Eckhardt. In IEEE +// Transactions on Computers, Vol. 50, No. 3, 2001. +// +// "An Implementation of Swing Modulo Scheduling With Extensions for +// Superblocks", by T. Lattner, Master's Thesis, University of Illinois at +// Urbana-Champaign, 2005. +// +// +// The SMS algorithm consists of three main steps after computing the minimal +// initiation interval (MII). +// 1) Analyze the dependence graph and compute information about each +// instruction in the graph. +// 2) Order the nodes (instructions) by priority based upon the heuristics +// described in the algorithm. +// 3) Attempt to schedule the nodes in the specified order using the MII. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_CODEGEN_MACHINEPIPELINER_H +#define LLVM_LIB_CODEGEN_MACHINEPIPELINER_H + +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/RegisterClassInfo.h" +#include "llvm/CodeGen/ScheduleDAGInstrs.h" +#include "llvm/CodeGen/TargetInstrInfo.h" + +namespace llvm { + +class NodeSet; +class SMSchedule; + +extern cl::opt SwpEnableCopyToPhi; + +/// The main class in the implementation of the target independent +/// software pipeliner pass. +class MachinePipeliner : public MachineFunctionPass { +public: + MachineFunction *MF = nullptr; + const MachineLoopInfo *MLI = nullptr; + const MachineDominatorTree *MDT = nullptr; + const InstrItineraryData *InstrItins; + const TargetInstrInfo *TII = nullptr; + RegisterClassInfo RegClassInfo; + +#ifndef NDEBUG + static int NumTries; +#endif + + /// Cache the target analysis information about the loop. + struct LoopInfo { + MachineBasicBlock *TBB = nullptr; + MachineBasicBlock *FBB = nullptr; + SmallVector BrCond; + MachineInstr *LoopInductionVar = nullptr; + MachineInstr *LoopCompare = nullptr; + }; + LoopInfo LI; + + static char ID; + + MachinePipeliner() : MachineFunctionPass(ID) { + initializeMachinePipelinerPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + +private: + void preprocessPhiNodes(MachineBasicBlock &B); + bool canPipelineLoop(MachineLoop &L); + bool scheduleLoop(MachineLoop &L); + bool swingModuloScheduler(MachineLoop &L); +}; + +/// This class builds the dependence graph for the instructions in a loop, +/// and attempts to schedule the instructions using the SMS algorithm. +class SwingSchedulerDAG : public ScheduleDAGInstrs { + MachinePipeliner &Pass; + /// The minimum initiation interval between iterations for this schedule. + unsigned MII = 0; + /// Set to true if a valid pipelined schedule is found for the loop. + bool Scheduled = false; + MachineLoop &Loop; + LiveIntervals &LIS; + const RegisterClassInfo &RegClassInfo; + + /// A toplogical ordering of the SUnits, which is needed for changing + /// dependences and iterating over the SUnits. + ScheduleDAGTopologicalSort Topo; + + struct NodeInfo { + int ASAP = 0; + int ALAP = 0; + int ZeroLatencyDepth = 0; + int ZeroLatencyHeight = 0; + + NodeInfo() = default; + }; + /// Computed properties for each node in the graph. + std::vector ScheduleInfo; + + enum OrderKind { BottomUp = 0, TopDown = 1 }; + /// Computed node ordering for scheduling. + SetVector NodeOrder; + + using NodeSetType = SmallVector; + using ValueMapTy = DenseMap; + using MBBVectorTy = SmallVectorImpl; + using InstrMapTy = DenseMap; + + /// Instructions to change when emitting the final schedule. + DenseMap> InstrChanges; + + /// We may create a new instruction, so remember it because it + /// must be deleted when the pass is finished. + SmallPtrSet NewMIs; + + /// Ordered list of DAG postprocessing steps. + std::vector> Mutations; + + /// Helper class to implement Johnson's circuit finding algorithm. + class Circuits { + std::vector &SUnits; + SetVector Stack; + BitVector Blocked; + SmallVector, 10> B; + SmallVector, 16> AdjK; + // Node to Index from ScheduleDAGTopologicalSort + std::vector *Node2Idx; + unsigned NumPaths; + static unsigned MaxPaths; + + public: + Circuits(std::vector &SUs, ScheduleDAGTopologicalSort &Topo) + : SUnits(SUs), Blocked(SUs.size()), B(SUs.size()), AdjK(SUs.size()) { + Node2Idx = new std::vector(SUs.size()); + unsigned Idx = 0; + for (const auto &NodeNum : Topo) + Node2Idx->at(NodeNum) = Idx++; + } + + ~Circuits() { delete Node2Idx; } + + /// Reset the data structures used in the circuit algorithm. + void reset() { + Stack.clear(); + Blocked.reset(); + B.assign(SUnits.size(), SmallPtrSet()); + NumPaths = 0; + } + + void createAdjacencyStructure(SwingSchedulerDAG *DAG); + bool circuit(int V, int S, NodeSetType &NodeSets, bool HasBackedge = false); + void unblock(int U); + }; + + struct CopyToPhiMutation : public ScheduleDAGMutation { + void apply(ScheduleDAGInstrs *DAG) override; + }; + +public: + SwingSchedulerDAG(MachinePipeliner &P, MachineLoop &L, LiveIntervals &lis, + const RegisterClassInfo &rci) + : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), Loop(L), LIS(lis), + RegClassInfo(rci), Topo(SUnits, &ExitSU) { + P.MF->getSubtarget().getSMSMutations(Mutations); + if (SwpEnableCopyToPhi) + Mutations.push_back(llvm::make_unique()); + } + + void schedule() override; + void finishBlock() override; + + /// Return true if the loop kernel has been scheduled. + bool hasNewSchedule() { return Scheduled; } + + /// Return the earliest time an instruction may be scheduled. + int getASAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ASAP; } + + /// Return the latest time an instruction my be scheduled. + int getALAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ALAP; } + + /// The mobility function, which the number of slots in which + /// an instruction may be scheduled. + int getMOV(SUnit *Node) { return getALAP(Node) - getASAP(Node); } + + /// The depth, in the dependence graph, for a node. + unsigned getDepth(SUnit *Node) { return Node->getDepth(); } + + /// The maximum unweighted length of a path from an arbitrary node to the + /// given node in which each edge has latency 0 + int getZeroLatencyDepth(SUnit *Node) { + return ScheduleInfo[Node->NodeNum].ZeroLatencyDepth; + } + + /// The height, in the dependence graph, for a node. + unsigned getHeight(SUnit *Node) { return Node->getHeight(); } + + /// The maximum unweighted length of a path from the given node to an + /// arbitrary node in which each edge has latency 0 + int getZeroLatencyHeight(SUnit *Node) { + return ScheduleInfo[Node->NodeNum].ZeroLatencyHeight; + } + + /// Return true if the dependence is a back-edge in the data dependence graph. + /// Since the DAG doesn't contain cycles, we represent a cycle in the graph + /// using an anti dependence from a Phi to an instruction. + bool isBackedge(SUnit *Source, const SDep &Dep) { + if (Dep.getKind() != SDep::Anti) + return false; + return Source->getInstr()->isPHI() || Dep.getSUnit()->getInstr()->isPHI(); + } + + bool isLoopCarriedDep(SUnit *Source, const SDep &Dep, bool isSucc = true); + + /// The distance function, which indicates that operation V of iteration I + /// depends on operations U of iteration I-distance. + unsigned getDistance(SUnit *U, SUnit *V, const SDep &Dep) { + // Instructions that feed a Phi have a distance of 1. Computing larger + // values for arrays requires data dependence information. + if (V->getInstr()->isPHI() && Dep.getKind() == SDep::Anti) + return 1; + return 0; + } + + /// Set the Minimum Initiation Interval for this schedule attempt. + void setMII(unsigned mii) { MII = mii; } + + void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule); + + void fixupRegisterOverlaps(std::deque &Instrs); + + /// Return the new base register that was stored away for the changed + /// instruction. + unsigned getInstrBaseReg(SUnit *SU) { + DenseMap>::iterator It = + InstrChanges.find(SU); + if (It != InstrChanges.end()) + return It->second.first; + return 0; + } + + void addMutation(std::unique_ptr Mutation) { + Mutations.push_back(std::move(Mutation)); + } + + static bool classof(const ScheduleDAGInstrs *DAG) { return true; } + +private: + void addLoopCarriedDependences(AliasAnalysis *AA); + void updatePhiDependences(); + void changeDependences(); + unsigned calculateResMII(); + unsigned calculateRecMII(NodeSetType &RecNodeSets); + void findCircuits(NodeSetType &NodeSets); + void fuseRecs(NodeSetType &NodeSets); + void removeDuplicateNodes(NodeSetType &NodeSets); + void computeNodeFunctions(NodeSetType &NodeSets); + void registerPressureFilter(NodeSetType &NodeSets); + void colocateNodeSets(NodeSetType &NodeSets); + void checkNodeSets(NodeSetType &NodeSets); + void groupRemainingNodes(NodeSetType &NodeSets); + void addConnectedNodes(SUnit *SU, NodeSet &NewSet, + SetVector &NodesAdded); + void computeNodeOrder(NodeSetType &NodeSets); + void checkValidNodeOrder(const NodeSetType &Circuits) const; + bool schedulePipeline(SMSchedule &Schedule); + void generatePipelinedLoop(SMSchedule &Schedule); + void generateProlog(SMSchedule &Schedule, unsigned LastStage, + MachineBasicBlock *KernelBB, ValueMapTy *VRMap, + MBBVectorTy &PrologBBs); + void generateEpilog(SMSchedule &Schedule, unsigned LastStage, + MachineBasicBlock *KernelBB, ValueMapTy *VRMap, + MBBVectorTy &EpilogBBs, MBBVectorTy &PrologBBs); + void generateExistingPhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1, + MachineBasicBlock *BB2, MachineBasicBlock *KernelBB, + SMSchedule &Schedule, ValueMapTy *VRMap, + InstrMapTy &InstrMap, unsigned LastStageNum, + unsigned CurStageNum, bool IsLast); + void generatePhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1, + MachineBasicBlock *BB2, MachineBasicBlock *KernelBB, + SMSchedule &Schedule, ValueMapTy *VRMap, + InstrMapTy &InstrMap, unsigned LastStageNum, + unsigned CurStageNum, bool IsLast); + void removeDeadInstructions(MachineBasicBlock *KernelBB, + MBBVectorTy &EpilogBBs); + void splitLifetimes(MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs, + SMSchedule &Schedule); + void addBranches(MBBVectorTy &PrologBBs, MachineBasicBlock *KernelBB, + MBBVectorTy &EpilogBBs, SMSchedule &Schedule, + ValueMapTy *VRMap); + bool computeDelta(MachineInstr &MI, unsigned &Delta); + void updateMemOperands(MachineInstr &NewMI, MachineInstr &OldMI, + unsigned Num); + MachineInstr *cloneInstr(MachineInstr *OldMI, unsigned CurStageNum, + unsigned InstStageNum); + MachineInstr *cloneAndChangeInstr(MachineInstr *OldMI, unsigned CurStageNum, + unsigned InstStageNum, + SMSchedule &Schedule); + void updateInstruction(MachineInstr *NewMI, bool LastDef, + unsigned CurStageNum, unsigned InstrStageNum, + SMSchedule &Schedule, ValueMapTy *VRMap); + MachineInstr *findDefInLoop(unsigned Reg); + unsigned getPrevMapVal(unsigned StageNum, unsigned PhiStage, unsigned LoopVal, + unsigned LoopStage, ValueMapTy *VRMap, + MachineBasicBlock *BB); + void rewritePhiValues(MachineBasicBlock *NewBB, unsigned StageNum, + SMSchedule &Schedule, ValueMapTy *VRMap, + InstrMapTy &InstrMap); + void rewriteScheduledInstr(MachineBasicBlock *BB, SMSchedule &Schedule, + InstrMapTy &InstrMap, unsigned CurStageNum, + unsigned PhiNum, MachineInstr *Phi, + unsigned OldReg, unsigned NewReg, + unsigned PrevReg = 0); + bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos, + unsigned &OffsetPos, unsigned &NewBase, + int64_t &NewOffset); + void postprocessDAG(); +}; + +/// A NodeSet contains a set of SUnit DAG nodes with additional information +/// that assigns a priority to the set. +class NodeSet { + SetVector Nodes; + bool HasRecurrence = false; + unsigned RecMII = 0; + int MaxMOV = 0; + unsigned MaxDepth = 0; + unsigned Colocate = 0; + SUnit *ExceedPressure = nullptr; + unsigned Latency = 0; + +public: + using iterator = SetVector::const_iterator; + + NodeSet() = default; + NodeSet(iterator S, iterator E) : Nodes(S, E), HasRecurrence(true) { + Latency = 0; + for (unsigned i = 0, e = Nodes.size(); i < e; ++i) + for (const SDep &Succ : Nodes[i]->Succs) + if (Nodes.count(Succ.getSUnit())) + Latency += Succ.getLatency(); + } + + bool insert(SUnit *SU) { return Nodes.insert(SU); } + + void insert(iterator S, iterator E) { Nodes.insert(S, E); } + + template bool remove_if(UnaryPredicate P) { + return Nodes.remove_if(P); + } + + unsigned count(SUnit *SU) const { return Nodes.count(SU); } + + bool hasRecurrence() { return HasRecurrence; }; + + unsigned size() const { return Nodes.size(); } + + bool empty() const { return Nodes.empty(); } + + SUnit *getNode(unsigned i) const { return Nodes[i]; }; + + void setRecMII(unsigned mii) { RecMII = mii; }; + + void setColocate(unsigned c) { Colocate = c; }; + + void setExceedPressure(SUnit *SU) { ExceedPressure = SU; } + + bool isExceedSU(SUnit *SU) { return ExceedPressure == SU; } + + int compareRecMII(NodeSet &RHS) { return RecMII - RHS.RecMII; } + + int getRecMII() { return RecMII; } + + /// Summarize node functions for the entire node set. + void computeNodeSetInfo(SwingSchedulerDAG *SSD) { + for (SUnit *SU : *this) { + MaxMOV = std::max(MaxMOV, SSD->getMOV(SU)); + MaxDepth = std::max(MaxDepth, SSD->getDepth(SU)); + } + } + + unsigned getLatency() { return Latency; } + + unsigned getMaxDepth() { return MaxDepth; } + + void clear() { + Nodes.clear(); + RecMII = 0; + HasRecurrence = false; + MaxMOV = 0; + MaxDepth = 0; + Colocate = 0; + ExceedPressure = nullptr; + } + + operator SetVector &() { return Nodes; } + + /// Sort the node sets by importance. First, rank them by recurrence MII, + /// then by mobility (least mobile done first), and finally by depth. + /// Each node set may contain a colocate value which is used as the first + /// tie breaker, if it's set. + bool operator>(const NodeSet &RHS) const { + if (RecMII == RHS.RecMII) { + if (Colocate != 0 && RHS.Colocate != 0 && Colocate != RHS.Colocate) + return Colocate < RHS.Colocate; + if (MaxMOV == RHS.MaxMOV) + return MaxDepth > RHS.MaxDepth; + return MaxMOV < RHS.MaxMOV; + } + return RecMII > RHS.RecMII; + } + + bool operator==(const NodeSet &RHS) const { + return RecMII == RHS.RecMII && MaxMOV == RHS.MaxMOV && + MaxDepth == RHS.MaxDepth; + } + + bool operator!=(const NodeSet &RHS) const { return !operator==(RHS); } + + iterator begin() { return Nodes.begin(); } + iterator end() { return Nodes.end(); } + void print(raw_ostream &os) const; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + LLVM_DUMP_METHOD void dump() const; +#endif +}; + +/// This class represents the scheduled code. The main data structure is a +/// map from scheduled cycle to instructions. During scheduling, the +/// data structure explicitly represents all stages/iterations. When +/// the algorithm finshes, the schedule is collapsed into a single stage, +/// which represents instructions from different loop iterations. +/// +/// The SMS algorithm allows negative values for cycles, so the first cycle +/// in the schedule is the smallest cycle value. +class SMSchedule { +private: + /// Map from execution cycle to instructions. + DenseMap> ScheduledInstrs; + + /// Map from instruction to execution cycle. + std::map InstrToCycle; + + /// Map for each register and the max difference between its uses and def. + /// The first element in the pair is the max difference in stages. The + /// second is true if the register defines a Phi value and loop value is + /// scheduled before the Phi. + std::map> RegToStageDiff; + + /// Keep track of the first cycle value in the schedule. It starts + /// as zero, but the algorithm allows negative values. + int FirstCycle = 0; + + /// Keep track of the last cycle value in the schedule. + int LastCycle = 0; + + /// The initiation interval (II) for the schedule. + int InitiationInterval = 0; + + /// Target machine information. + const TargetSubtargetInfo &ST; + + /// Virtual register information. + MachineRegisterInfo &MRI; + + std::unique_ptr Resources; + +public: + SMSchedule(MachineFunction *mf) + : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), + Resources(ST.getInstrInfo()->CreateTargetScheduleState(ST)) {} + + void reset() { + ScheduledInstrs.clear(); + InstrToCycle.clear(); + RegToStageDiff.clear(); + FirstCycle = 0; + LastCycle = 0; + InitiationInterval = 0; + } + + /// Set the initiation interval for this schedule. + void setInitiationInterval(int ii) { InitiationInterval = ii; } + + /// Return the first cycle in the completed schedule. This + /// can be a negative value. + int getFirstCycle() const { return FirstCycle; } + + /// Return the last cycle in the finalized schedule. + int getFinalCycle() const { return FirstCycle + InitiationInterval - 1; } + + /// Return the cycle of the earliest scheduled instruction in the dependence + /// chain. + int earliestCycleInChain(const SDep &Dep); + + /// Return the cycle of the latest scheduled instruction in the dependence + /// chain. + int latestCycleInChain(const SDep &Dep); + + void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart, + int *MinEnd, int *MaxStart, int II, SwingSchedulerDAG *DAG); + bool insert(SUnit *SU, int StartCycle, int EndCycle, int II); + + /// Iterators for the cycle to instruction map. + using sched_iterator = DenseMap>::iterator; + using const_sched_iterator = + DenseMap>::const_iterator; + + /// Return true if the instruction is scheduled at the specified stage. + bool isScheduledAtStage(SUnit *SU, unsigned StageNum) { + return (stageScheduled(SU) == (int)StageNum); + } + + /// Return the stage for a scheduled instruction. Return -1 if + /// the instruction has not been scheduled. + int stageScheduled(SUnit *SU) const { + std::map::const_iterator it = InstrToCycle.find(SU); + if (it == InstrToCycle.end()) + return -1; + return (it->second - FirstCycle) / InitiationInterval; + } + + /// Return the cycle for a scheduled instruction. This function normalizes + /// the first cycle to be 0. + unsigned cycleScheduled(SUnit *SU) const { + std::map::const_iterator it = InstrToCycle.find(SU); + assert(it != InstrToCycle.end() && "Instruction hasn't been scheduled."); + return (it->second - FirstCycle) % InitiationInterval; + } + + /// Return the maximum stage count needed for this schedule. + unsigned getMaxStageCount() { + return (LastCycle - FirstCycle) / InitiationInterval; + } + + /// Return the max. number of stages/iterations that can occur between a + /// register definition and its uses. + unsigned getStagesForReg(int Reg, unsigned CurStage) { + std::pair Stages = RegToStageDiff[Reg]; + if (CurStage > getMaxStageCount() && Stages.first == 0 && Stages.second) + return 1; + return Stages.first; + } + + /// The number of stages for a Phi is a little different than other + /// instructions. The minimum value computed in RegToStageDiff is 1 + /// because we assume the Phi is needed for at least 1 iteration. + /// This is not the case if the loop value is scheduled prior to the + /// Phi in the same stage. This function returns the number of stages + /// or iterations needed between the Phi definition and any uses. + unsigned getStagesForPhi(int Reg) { + std::pair Stages = RegToStageDiff[Reg]; + if (Stages.second) + return Stages.first; + return Stages.first - 1; + } + + /// Return the instructions that are scheduled at the specified cycle. + std::deque &getInstructions(int cycle) { + return ScheduledInstrs[cycle]; + } + + bool isValidSchedule(SwingSchedulerDAG *SSD); + void finalizeSchedule(SwingSchedulerDAG *SSD); + void orderDependence(SwingSchedulerDAG *SSD, SUnit *SU, + std::deque &Insts); + bool isLoopCarried(SwingSchedulerDAG *SSD, MachineInstr &Phi); + bool isLoopCarriedDefOfUse(SwingSchedulerDAG *SSD, MachineInstr *Def, + MachineOperand &MO); + void print(raw_ostream &os) const; + void dump() const; +}; + +} // end namespace llvm + +#endif // LLVM_LIB_CODEGEN_MACHINEPIPELINER_H diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 5bf4a49c8b3..fef010a23ef 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -689,15 +689,14 @@ public: unsigned MinNumRegs = 0); /// Constrain the register class or the register bank of the virtual register - /// \p Reg to be a common subclass and a common bank of both registers - /// provided respectively. Do nothing if any of the attributes (classes, - /// banks, or low-level types) of the registers are deemed incompatible, or if - /// the resulting register will have a class smaller than before and of size - /// less than \p MinNumRegs. Return true if such register attributes exist, - /// false otherwise. + /// \p Reg (and low-level type) to be a common subclass or a common bank of + /// both registers provided respectively (and a common low-level type). Do + /// nothing if any of the attributes (classes, banks, or low-level types) of + /// the registers are deemed incompatible, or if the resulting register will + /// have a class smaller than before and of size less than \p MinNumRegs. + /// Return true if such register attributes exist, false otherwise. /// - /// \note Assumes that each register has either a low-level type or a class - /// assigned, but not both. Use this method instead of constrainRegClass and + /// \note Use this method instead of constrainRegClass and /// RegisterBankInfo::constrainGenericRegister everywhere but SelectionDAG /// ISel / FastISel and GlobalISel's InstructionSelect pass respectively. bool constrainRegAttrs(unsigned Reg, unsigned ConstrainingReg, @@ -717,6 +716,10 @@ public: unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name = ""); + /// Create and return a new virtual register in the function with the same + /// attributes as the given register. + unsigned cloneVirtualRegister(unsigned VReg, StringRef Name = ""); + /// Get the low-level type of \p Reg or LLT{} if Reg is not a generic /// (target independent) virtual register. LLT getType(unsigned Reg) const { diff --git a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h index 85ffa4eda2b..4bc31ae7c61 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h @@ -132,17 +132,19 @@ struct MachineSchedContext { /// MachineSchedRegistry provides a selection of available machine instruction /// schedulers. -class MachineSchedRegistry : public MachinePassRegistryNode { +class MachineSchedRegistry + : public MachinePassRegistryNode< + ScheduleDAGInstrs *(*)(MachineSchedContext *)> { public: using ScheduleDAGCtor = ScheduleDAGInstrs *(*)(MachineSchedContext *); // RegisterPassParser requires a (misnamed) FunctionPassCtor type. using FunctionPassCtor = ScheduleDAGCtor; - static MachinePassRegistry Registry; + static MachinePassRegistry Registry; MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C) - : MachinePassRegistryNode(N, D, (MachinePassCtor)C) { + : MachinePassRegistryNode(N, D, C) { Registry.Add(this); } @@ -158,7 +160,7 @@ public: return (MachineSchedRegistry *)Registry.getList(); } - static void setListener(MachinePassRegistryListener *L) { + static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } }; @@ -466,6 +468,9 @@ public: PressureDiff &getPressureDiff(const SUnit *SU) { return SUPressureDiffs[SU->NodeNum]; } + const PressureDiff &getPressureDiff(const SUnit *SU) const { + return SUPressureDiffs[SU->NodeNum]; + } /// Compute a DFSResult after DAG building is complete, and before any /// queue comparisons. @@ -491,6 +496,8 @@ public: /// Compute the cyclic critical path through the DAG. unsigned computeCyclicCriticalPath(); + void dump() const override; + protected: // Top-Level entry points for the schedule() driver... @@ -787,7 +794,7 @@ public: /// Represent the type of SchedCandidate found within a single queue. /// pickNodeBidirectional depends on these listed by decreasing priority. enum CandReason : uint8_t { - NoCand, Only1, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak, + NoCand, Only1, PhysReg, RegExcess, RegCritical, Stall, Cluster, Weak, RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce, TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder}; @@ -895,6 +902,10 @@ protected: #ifndef NDEBUG void traceCandidate(const SchedCandidate &Cand); #endif + +private: + bool shouldReduceLatency(const CandPolicy &Policy, SchedBoundary &CurrZone, + bool ComputeRemLatency, unsigned &RemLatency) const; }; // Utility functions used by heuristics in tryCandidate(). @@ -917,7 +928,7 @@ bool tryPressure(const PressureChange &TryP, const TargetRegisterInfo *TRI, const MachineFunction &MF); unsigned getWeakLeft(const SUnit *SU, bool isTop); -int biasPhysRegCopy(const SUnit *SU, bool isTop); +int biasPhysReg(const SUnit *SU, bool isTop); /// GenericScheduler shrinks the unscheduled zone using heuristics to balance /// the schedule. @@ -995,7 +1006,7 @@ protected: const RegPressureTracker &RPTracker, SchedCandidate &Candidate); - void reschedulePhysRegCopies(SUnit *SU, bool isTop); + void reschedulePhysReg(SUnit *SU, bool isTop); }; /// PostGenericScheduler - Interface to the scheduling algorithm used by diff --git a/contrib/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm/include/llvm/CodeGen/Passes.h index cb12b14f443..acf1ebb5bc8 100644 --- a/contrib/llvm/include/llvm/CodeGen/Passes.h +++ b/contrib/llvm/include/llvm/CodeGen/Passes.h @@ -379,14 +379,20 @@ namespace llvm { /// FunctionPass *createInterleavedAccessPass(); + /// InterleavedLoadCombines Pass - This pass identifies interleaved loads and + /// combines them into wide loads detectable by InterleavedAccessPass + /// + FunctionPass *createInterleavedLoadCombinePass(); + /// LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all /// TLS variables for the emulated TLS model. /// ModulePass *createLowerEmuTLSPass(); - /// This pass lowers the \@llvm.load.relative intrinsic to instructions. - /// This is unsafe to do earlier because a pass may combine the constant - /// initializer into the load, which may result in an overflowing evaluation. + /// This pass lowers the \@llvm.load.relative and \@llvm.objc.* intrinsics to + /// instructions. This is unsafe to do earlier because a pass may combine the + /// constant initializer into the load, which may result in an overflowing + /// evaluation. ModulePass *createPreISelIntrinsicLoweringPass(); /// GlobalMerge - This pass merges internal (by default) globals into structs diff --git a/contrib/llvm/include/llvm/CodeGen/PreISelIntrinsicLowering.h b/contrib/llvm/include/llvm/CodeGen/PreISelIntrinsicLowering.h index 7a007eb8bce..b7f83e515b7 100644 --- a/contrib/llvm/include/llvm/CodeGen/PreISelIntrinsicLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/PreISelIntrinsicLowering.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This pass implements IR lowering for the llvm.load.relative intrinsic. +// This pass implements IR lowering for the llvm.load.relative and llvm.objc.* +// intrinsics. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_PREISELINTRINSICLOWERING_H diff --git a/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h b/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h index bdf0bb73154..f66191bc9fb 100644 --- a/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h +++ b/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h @@ -36,7 +36,7 @@ raw_ostream &operator<<(raw_ostream &OS, const PseudoSourceValue* PSV); /// below the stack frame (e.g., argument space), or constant pool. class PseudoSourceValue { public: - enum PSVKind { + enum PSVKind : unsigned { Stack, GOT, JumpTable, @@ -48,7 +48,7 @@ public: }; private: - PSVKind Kind; + unsigned Kind; unsigned AddressSpace; friend raw_ostream &llvm::operator<<(raw_ostream &OS, const PseudoSourceValue* PSV); @@ -60,11 +60,11 @@ private: virtual void printCustom(raw_ostream &O) const; public: - explicit PseudoSourceValue(PSVKind Kind, const TargetInstrInfo &TII); + explicit PseudoSourceValue(unsigned Kind, const TargetInstrInfo &TII); virtual ~PseudoSourceValue(); - PSVKind kind() const { return Kind; } + unsigned kind() const { return Kind; } bool isStack() const { return Kind == Stack; } bool isGOT() const { return Kind == GOT; } @@ -116,7 +116,7 @@ public: class CallEntryPseudoSourceValue : public PseudoSourceValue { protected: - CallEntryPseudoSourceValue(PSVKind Kind, const TargetInstrInfo &TII); + CallEntryPseudoSourceValue(unsigned Kind, const TargetInstrInfo &TII); public: bool isConstant(const MachineFrameInfo *) const override; diff --git a/contrib/llvm/include/llvm/CodeGen/RegAllocRegistry.h b/contrib/llvm/include/llvm/CodeGen/RegAllocRegistry.h index 481747dc163..b518fbb9c9d 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegAllocRegistry.h +++ b/contrib/llvm/include/llvm/CodeGen/RegAllocRegistry.h @@ -26,14 +26,14 @@ class FunctionPass; /// RegisterRegAlloc class - Track the registration of register allocators. /// //===----------------------------------------------------------------------===// -class RegisterRegAlloc : public MachinePassRegistryNode { +class RegisterRegAlloc : public MachinePassRegistryNode { public: using FunctionPassCtor = FunctionPass *(*)(); - static MachinePassRegistry Registry; + static MachinePassRegistry Registry; RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) - : MachinePassRegistryNode(N, D, (MachinePassCtor)C) { + : MachinePassRegistryNode(N, D, C) { Registry.Add(this); } @@ -48,15 +48,11 @@ public: return (RegisterRegAlloc *)Registry.getList(); } - static FunctionPassCtor getDefault() { - return (FunctionPassCtor)Registry.getDefault(); - } + static FunctionPassCtor getDefault() { return Registry.getDefault(); } - static void setDefault(FunctionPassCtor C) { - Registry.setDefault((MachinePassCtor)C); - } + static void setDefault(FunctionPassCtor C) { Registry.setDefault(C); } - static void setListener(MachinePassRegistryListener *L) { + static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } }; diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h b/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h index efd175eeed3..efecc61d9c3 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h @@ -29,7 +29,7 @@ namespace llvm { class Function; -class TargetMachine; +class LLVMTargetMachine; class PhysicalRegisterUsageInfo : public ImmutablePass { public: @@ -41,7 +41,7 @@ public: } /// Set TargetMachine which is used to print analysis. - void setTargetMachine(const TargetMachine &TM); + void setTargetMachine(const LLVMTargetMachine &TM); bool doInitialization(Module &M) override; @@ -63,7 +63,7 @@ private: /// and 1 means content of register will be preserved around function call. DenseMap> RegMasks; - const TargetMachine *TM; + const LLVMTargetMachine *TM; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h index 56adc2e2fbf..0870d67db39 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h @@ -33,15 +33,15 @@ namespace llvm { template class GraphWriter; +class LLVMTargetMachine; class MachineFunction; class MachineRegisterInfo; class MCInstrDesc; struct MCSchedClassDesc; -class ScheduleDAG; class SDNode; class SUnit; +class ScheduleDAG; class TargetInstrInfo; -class TargetMachine; class TargetRegisterClass; class TargetRegisterInfo; @@ -236,8 +236,7 @@ class TargetRegisterInfo; Contents.Reg = Reg; } - raw_ostream &print(raw_ostream &O, - const TargetRegisterInfo *TRI = nullptr) const; + void dump(const TargetRegisterInfo *TRI = nullptr) const; }; template <> @@ -459,12 +458,7 @@ class TargetRegisterInfo; /// edge occurs first. void biasCriticalPath(); - void dump(const ScheduleDAG *G) const; - void dumpAll(const ScheduleDAG *G) const; - raw_ostream &print(raw_ostream &O, - const SUnit *Entry = nullptr, - const SUnit *Exit = nullptr) const; - raw_ostream &print(raw_ostream &O, const ScheduleDAG *G) const; + void dumpAttributes() const; private: void ComputeDepth(); @@ -564,7 +558,7 @@ class TargetRegisterInfo; class ScheduleDAG { public: - const TargetMachine &TM; ///< Target processor + const LLVMTargetMachine &TM; ///< Target processor const TargetInstrInfo *TII; ///< Target instruction information const TargetRegisterInfo *TRI; ///< Target processor register info MachineFunction &MF; ///< Machine function @@ -597,7 +591,9 @@ class TargetRegisterInfo; virtual void viewGraph(const Twine &Name, const Twine &Title); virtual void viewGraph(); - virtual void dumpNode(const SUnit *SU) const = 0; + virtual void dumpNode(const SUnit &SU) const = 0; + virtual void dump() const = 0; + void dumpNodeName(const SUnit &SU) const; /// Returns a label for an SUnit node in a visualization of the ScheduleDAG. virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0; @@ -614,6 +610,9 @@ class TargetRegisterInfo; unsigned VerifyScheduledDAG(bool isBottomUp); #endif + protected: + void dumpNodeAll(const SUnit &SU) const; + private: /// Returns the MCInstrDesc of this SDNode or NULL. const MCInstrDesc *getNodeDesc(const SDNode *Node) const; diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h index 520a23846f6..daad18125db 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -327,7 +327,8 @@ namespace llvm { /// whole MachineFunction. By default does nothing. virtual void finalizeSchedule() {} - void dumpNode(const SUnit *SU) const override; + void dumpNode(const SUnit &SU) const override; + void dump() const override; /// Returns a label for a DAG node that points to an instruction. std::string getGraphNodeLabel(const SUnit *SU) const override; diff --git a/contrib/llvm/include/llvm/CodeGen/SchedulerRegistry.h b/contrib/llvm/include/llvm/CodeGen/SchedulerRegistry.h index badf927d0e9..fbe559f2555 100644 --- a/contrib/llvm/include/llvm/CodeGen/SchedulerRegistry.h +++ b/contrib/llvm/include/llvm/CodeGen/SchedulerRegistry.h @@ -29,16 +29,19 @@ namespace llvm { class ScheduleDAGSDNodes; class SelectionDAGISel; -class RegisterScheduler : public MachinePassRegistryNode { +class RegisterScheduler + : public MachinePassRegistryNode< + ScheduleDAGSDNodes *(*)(SelectionDAGISel *, CodeGenOpt::Level)> { public: using FunctionPassCtor = ScheduleDAGSDNodes *(*)(SelectionDAGISel*, CodeGenOpt::Level); - static MachinePassRegistry Registry; + static MachinePassRegistry Registry; RegisterScheduler(const char *N, const char *D, FunctionPassCtor C) - : MachinePassRegistryNode(N, D, (MachinePassCtor)C) - { Registry.Add(this); } + : MachinePassRegistryNode(N, D, C) { + Registry.Add(this); + } ~RegisterScheduler() { Registry.Remove(this); } @@ -51,7 +54,7 @@ public: return (RegisterScheduler *)Registry.getList(); } - static void setListener(MachinePassRegistryListener *L) { + static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } }; diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h index 888f9425ff9..67fe87fc96a 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -28,7 +28,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/DivergenceAnalysis.h" +#include "llvm/Analysis/LegacyDivergenceAnalysis.h" #include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/ISDOpcodes.h" @@ -188,8 +188,8 @@ public: return DbgValues.empty() && ByvalParmDbgValues.empty() && DbgLabels.empty(); } - ArrayRef getSDDbgValues(const SDNode *Node) { - DbgValMapType::iterator I = DbgValMap.find(Node); + ArrayRef getSDDbgValues(const SDNode *Node) const { + auto I = DbgValMap.find(Node); if (I != DbgValMap.end()) return I->second; return ArrayRef(); @@ -229,7 +229,7 @@ class SelectionDAG { LLVMContext *Context; CodeGenOpt::Level OptLevel; - DivergenceAnalysis * DA = nullptr; + LegacyDivergenceAnalysis * DA = nullptr; FunctionLoweringInfo * FLI = nullptr; /// The function-level optimization remark emitter. Used to emit remarks @@ -308,6 +308,9 @@ public: : DAGUpdateListener(DAG), Callback(std::move(Callback)) {} void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); } + + private: + virtual void anchor(); }; /// When true, additional steps are taken to @@ -382,7 +385,7 @@ public: /// Prepare this SelectionDAG to process code in the given MachineFunction. void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE, Pass *PassPtr, const TargetLibraryInfo *LibraryInfo, - DivergenceAnalysis * Divergence); + LegacyDivergenceAnalysis * Divergence); void setFunctionLoweringInfo(FunctionLoweringInfo * FuncInfo) { FLI = FuncInfo; @@ -471,7 +474,9 @@ public: return Root; } +#ifndef NDEBUG void VerifyDAGDiverence(); +#endif /// This iterates over the nodes in the SelectionDAG, folding /// certain types of nodes together, or eliminating superfluous nodes. The @@ -784,24 +789,6 @@ public: /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); - /// Return an operation which will any-extend the low lanes of the operand - /// into the specified vector type. For example, - /// this can convert a v16i8 into a v4i32 by any-extending the low four - /// lanes of the operand from i8 to i32. - SDValue getAnyExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT); - - /// Return an operation which will sign extend the low lanes of the operand - /// into the specified vector type. For example, - /// this can convert a v16i8 into a v4i32 by sign extending the low four - /// lanes of the operand from i8 to i32. - SDValue getSignExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT); - - /// Return an operation which will zero extend the low lanes of the operand - /// into the specified vector type. For example, - /// this can convert a v16i8 into a v4i32 by zero extending the low four - /// lanes of the operand from i8 to i32. - SDValue getZeroExtendVectorInReg(SDValue Op, const SDLoc &DL, EVT VT); - /// Convert Op, which must be of integer type, to the integer type VT, /// by using an extension appropriate for the target's /// BooleanContent for type OpVT or truncating it. @@ -945,41 +932,45 @@ public: Type *SizeTy, unsigned ElemSz, bool isTailCall, MachinePointerInfo DstPtrInfo); - /// Helper function to make it easier to build SetCC's if you just - /// have an ISD::CondCode instead of an SDValue. - /// + /// Helper function to make it easier to build SetCC's if you just have an + /// ISD::CondCode instead of an SDValue. SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond) { assert(LHS.getValueType().isVector() == RHS.getValueType().isVector() && - "Cannot compare scalars to vectors"); + "Cannot compare scalars to vectors"); assert(LHS.getValueType().isVector() == VT.isVector() && - "Cannot compare scalars to vectors"); + "Cannot compare scalars to vectors"); assert(Cond != ISD::SETCC_INVALID && - "Cannot create a setCC of an invalid node."); + "Cannot create a setCC of an invalid node."); return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } - /// Helper function to make it easier to build Select's if you just - /// have operands and don't want to check for vector. + /// Helper function to make it easier to build Select's if you just have + /// operands and don't want to check for vector. SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS) { assert(LHS.getValueType() == RHS.getValueType() && "Cannot use select on differing types"); assert(VT.isVector() == LHS.getValueType().isVector() && "Cannot mix vectors and scalars"); - return getNode(Cond.getValueType().isVector() ? ISD::VSELECT : ISD::SELECT, DL, VT, - Cond, LHS, RHS); + auto Opcode = Cond.getValueType().isVector() ? ISD::VSELECT : ISD::SELECT; + return getNode(Opcode, DL, VT, Cond, LHS, RHS); } - /// Helper function to make it easier to build SelectCC's if you - /// just have an ISD::CondCode instead of an SDValue. - /// + /// Helper function to make it easier to build SelectCC's if you just have an + /// ISD::CondCode instead of an SDValue. SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond) { - return getNode(ISD::SELECT_CC, DL, True.getValueType(), - LHS, RHS, True, False, getCondCode(Cond)); + return getNode(ISD::SELECT_CC, DL, True.getValueType(), LHS, RHS, True, + False, getCondCode(Cond)); } + /// Try to simplify a select/vselect into 1 of its operands or a constant. + SDValue simplifySelect(SDValue Cond, SDValue TVal, SDValue FVal); + + /// Try to simplify a shift into 1 of its operands or a constant. + SDValue simplifyShift(SDValue X, SDValue Y); + /// VAArg produces a result and token chain, and takes a pointer /// and a source value as input. SDValue getVAArg(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, @@ -1140,6 +1131,13 @@ public: /// Expand the specified \c ISD::VACOPY node as the Legalize pass would. SDValue expandVACopy(SDNode *Node); + /// Returs an GlobalAddress of the function from the current module with + /// name matching the given ExternalSymbol. Additionally can provide the + /// matched function. + /// Panics the function doesn't exists. + SDValue getSymbolFunctionGlobalAddress(SDValue Op, + Function **TargetFunction = nullptr); + /// *Mutate* the specified node in-place to have the /// specified operands. If the resultant node already exists in the DAG, /// this does not modify the specified node, instead it returns the node that @@ -1156,6 +1154,11 @@ public: SDValue Op3, SDValue Op4, SDValue Op5); SDNode *UpdateNodeOperands(SDNode *N, ArrayRef Ops); + /// *Mutate* the specified machine node's memory references to the provided + /// list. + void setNodeMemRefs(MachineSDNode *N, + ArrayRef NewMemRefs); + // Propagates the change in divergence to users void updateDivergence(SDNode * N); @@ -1346,7 +1349,7 @@ public: void AddDbgLabel(SDDbgLabel *DB); /// Get the debug values which reference the given SDNode. - ArrayRef GetDbgValues(const SDNode* SD) { + ArrayRef GetDbgValues(const SDNode* SD) const { return DbgInfo->getSDDbgValues(SD); } @@ -1429,15 +1432,15 @@ public: /// every vector element. /// Targets can implement the computeKnownBitsForTargetNode method in the /// TargetLowering class to allow target nodes to be understood. - void computeKnownBits(SDValue Op, KnownBits &Known, unsigned Depth = 0) const; + KnownBits computeKnownBits(SDValue Op, unsigned Depth = 0) const; /// Determine which bits of Op are known to be either zero or one and return /// them in Known. The DemandedElts argument allows us to only collect the /// known bits that are shared by the requested vector elements. /// Targets can implement the computeKnownBitsForTargetNode method in the /// TargetLowering class to allow target nodes to be understood. - void computeKnownBits(SDValue Op, KnownBits &Known, const APInt &DemandedElts, - unsigned Depth = 0) const; + KnownBits computeKnownBits(SDValue Op, const APInt &DemandedElts, + unsigned Depth = 0) const; /// Used to represent the possible overflow behavior of an operation. /// Never: the operation cannot overflow. @@ -1484,8 +1487,15 @@ public: /// X|Cst == X+Cst iff X&Cst = 0. bool isBaseWithConstantOffset(SDValue Op) const; - /// Test whether the given SDValue is known to never be NaN. - bool isKnownNeverNaN(SDValue Op) const; + /// Test whether the given SDValue is known to never be NaN. If \p SNaN is + /// true, returns if \p Op is known to never be a signaling NaN (it may still + /// be a qNaN). + bool isKnownNeverNaN(SDValue Op, bool SNaN = false, unsigned Depth = 0) const; + + /// \returns true if \p Op is known to never be a signaling NaN. + bool isKnownNeverSNaN(SDValue Op, unsigned Depth = 0) const { + return isKnownNeverNaN(Op, true, Depth); + } /// Test whether the given floating point SDValue is known to never be /// positive or negative zero. @@ -1503,6 +1513,27 @@ public: /// allow an 'add' to be transformed into an 'or'. bool haveNoCommonBitsSet(SDValue A, SDValue B) const; + /// Test whether \p V has a splatted value for all the demanded elements. + /// + /// On success \p UndefElts will indicate the elements that have UNDEF + /// values instead of the splat value, this is only guaranteed to be correct + /// for \p DemandedElts. + /// + /// NOTE: The function will return true for a demanded splat of UNDEF values. + bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts); + + /// Test whether \p V has a splatted value. + bool isSplatValue(SDValue V, bool AllowUndefs = false); + + /// Match a binop + shuffle pyramid that represents a horizontal reduction + /// over the elements of a vector starting from the EXTRACT_VECTOR_ELT node /p + /// Extract. The reduction must use one of the opcodes listed in /p + /// CandidateBinOps and on success /p BinOp will contain the matching opcode. + /// Returns the vector that is being reduced on, or SDValue() if a reduction + /// was not matched. + SDValue matchBinOpReduction(SDNode *Extract, ISD::NodeType &BinOp, + ArrayRef CandidateBinOps); + /// Utility function used by legalize and lowering to /// "unroll" a vector operation by splitting out the scalars and operating /// on each element individually. If the ResNE is 0, fully unroll the vector diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h index 580606441a9..2b2c48d57bc 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h @@ -45,18 +45,21 @@ public: IsIndexSignExt(IsIndexSignExt) {} SDValue getBase() { return Base; } + SDValue getBase() const { return Base; } SDValue getIndex() { return Index; } + SDValue getIndex() const { return Index; } - bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG) { + bool equalBaseIndex(const BaseIndexOffset &Other, + const SelectionDAG &DAG) const { int64_t Off; return equalBaseIndex(Other, DAG, Off); } - bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG, - int64_t &Off); + bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, + int64_t &Off) const; /// Parses tree in Ptr for base, index, offset addresses. - static BaseIndexOffset match(LSBaseSDNode *N, const SelectionDAG &DAG); + static BaseIndexOffset match(const LSBaseSDNode *N, const SelectionDAG &DAG); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 86df0af7303..6758c55c696 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -132,6 +132,7 @@ public: OPC_CheckChild2Same, OPC_CheckChild3Same, OPC_CheckPatternPredicate, OPC_CheckPredicate, + OPC_CheckPredicateWithOperands, OPC_CheckOpcode, OPC_SwitchOpcode, OPC_CheckType, @@ -267,6 +268,17 @@ public: llvm_unreachable("Tblgen should generate the implementation of this!"); } + /// CheckNodePredicateWithOperands - This function is generated by tblgen in + /// the target. + /// It runs node predicate number PredNo and returns true if it succeeds or + /// false if it fails. The number is a private implementation detail to the + /// code tblgen produces. + virtual bool CheckNodePredicateWithOperands( + SDNode *N, unsigned PredNo, + const SmallVectorImpl &Operands) const { + llvm_unreachable("Tblgen should generate the implementation of this!"); + } + virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N, unsigned PatternNo, SmallVectorImpl > &Result) { diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 1af22185d36..10f28417908 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -672,6 +672,12 @@ public: case ISD::STRICT_FLOG2: case ISD::STRICT_FRINT: case ISD::STRICT_FNEARBYINT: + case ISD::STRICT_FMAXNUM: + case ISD::STRICT_FMINNUM: + case ISD::STRICT_FCEIL: + case ISD::STRICT_FFLOOR: + case ISD::STRICT_FROUND: + case ISD::STRICT_FTRUNC: return true; } } @@ -1589,15 +1595,38 @@ bool isAllOnesConstant(SDValue V); /// Returns true if \p V is a constant integer one. bool isOneConstant(SDValue V); +/// Return the non-bitcasted source operand of \p V if it exists. +/// If \p V is not a bitcasted value, it is returned as-is. +SDValue peekThroughBitcasts(SDValue V); + +/// Return the non-bitcasted and one-use source operand of \p V if it exists. +/// If \p V is not a bitcasted one-use value, it is returned as-is. +SDValue peekThroughOneUseBitcasts(SDValue V); + /// Returns true if \p V is a bitwise not operation. Assumes that an all ones /// constant is canonicalized to be operand 1. bool isBitwiseNot(SDValue V); /// Returns the SDNode if it is a constant splat BuildVector or constant int. -ConstantSDNode *isConstOrConstSplat(SDValue N); +ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false); /// Returns the SDNode if it is a constant splat BuildVector or constant float. -ConstantFPSDNode *isConstOrConstSplatFP(SDValue N); +ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, bool AllowUndefs = false); + +/// Return true if the value is a constant 0 integer or a splatted vector of +/// a constant 0 integer (with no undefs). +/// Build vector implicit truncation is not an issue for null values. +bool isNullOrNullSplat(SDValue V); + +/// Return true if the value is a constant 1 integer or a splatted vector of a +/// constant 1 integer (with no undefs). +/// Does not permit build vector implicit truncation. +bool isOneOrOneSplat(SDValue V); + +/// Return true if the value is a constant -1 integer or a splatted vector of a +/// constant -1 integer (with no undefs). +/// Does not permit build vector implicit truncation. +bool isAllOnesOrAllOnesSplat(SDValue V); class GlobalAddressSDNode : public SDNode { friend class SelectionDAG; @@ -2113,12 +2142,15 @@ public: MachineMemOperand *MMO) : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {} - // In the both nodes address is Op1, mask is Op2: - // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value - // MaskedStoreSDNode (Chain, ptr, mask, data) + // MaskedLoadSDNode (Chain, ptr, mask, passthru) + // MaskedStoreSDNode (Chain, data, ptr, mask) // Mask is a vector of i1 elements - const SDValue &getBasePtr() const { return getOperand(1); } - const SDValue &getMask() const { return getOperand(2); } + const SDValue &getBasePtr() const { + return getOperand(getOpcode() == ISD::MLOAD ? 1 : 2); + } + const SDValue &getMask() const { + return getOperand(getOpcode() == ISD::MLOAD ? 2 : 3); + } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MLOAD || @@ -2143,7 +2175,10 @@ public: return static_cast(LoadSDNodeBits.ExtTy); } - const SDValue &getSrc0() const { return getOperand(3); } + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getMask() const { return getOperand(2); } + const SDValue &getPassThru() const { return getOperand(3); } + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MLOAD; } @@ -2175,7 +2210,9 @@ public: /// memory at base_addr. bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; } - const SDValue &getValue() const { return getOperand(3); } + const SDValue &getValue() const { return getOperand(1); } + const SDValue &getBasePtr() const { return getOperand(2); } + const SDValue &getMask() const { return getOperand(3); } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MSTORE; @@ -2201,7 +2238,6 @@ public: const SDValue &getBasePtr() const { return getOperand(3); } const SDValue &getIndex() const { return getOperand(4); } const SDValue &getMask() const { return getOperand(2); } - const SDValue &getValue() const { return getOperand(1); } const SDValue &getScale() const { return getOperand(5); } static bool classof(const SDNode *N) { @@ -2220,6 +2256,8 @@ public: EVT MemVT, MachineMemOperand *MMO) : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO) {} + const SDValue &getPassThru() const { return getOperand(1); } + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MGATHER; } @@ -2235,6 +2273,8 @@ public: EVT MemVT, MachineMemOperand *MMO) : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO) {} + const SDValue &getValue() const { return getOperand(1); } + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MSCATTER; } @@ -2243,32 +2283,60 @@ public: /// An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. +/// +/// Note that the only supported way to set the `memoperands` is by calling the +/// `SelectionDAG::setNodeMemRefs` function as the memory management happens +/// inside the DAG rather than in the node. class MachineSDNode : public SDNode { -public: - using mmo_iterator = MachineMemOperand **; - private: friend class SelectionDAG; MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs) : SDNode(Opc, Order, DL, VTs) {} - /// Memory reference descriptions for this instruction. - mmo_iterator MemRefs = nullptr; - mmo_iterator MemRefsEnd = nullptr; + // We use a pointer union between a single `MachineMemOperand` pointer and + // a pointer to an array of `MachineMemOperand` pointers. This is null when + // the number of these is zero, the single pointer variant used when the + // number is one, and the array is used for larger numbers. + // + // The array is allocated via the `SelectionDAG`'s allocator and so will + // always live until the DAG is cleaned up and doesn't require ownership here. + // + // We can't use something simpler like `TinyPtrVector` here because `SDNode` + // subclasses aren't managed in a conforming C++ manner. See the comments on + // `SelectionDAG::MorphNodeTo` which details what all goes on, but the + // constraint here is that these don't manage memory with their constructor or + // destructor and can be initialized to a good state even if they start off + // uninitialized. + PointerUnion MemRefs = {}; + + // Note that this could be folded into the above `MemRefs` member if doing so + // is advantageous at some point. We don't need to store this in most cases. + // However, at the moment this doesn't appear to make the allocation any + // smaller and makes the code somewhat simpler to read. + int NumMemRefs = 0; public: - mmo_iterator memoperands_begin() const { return MemRefs; } - mmo_iterator memoperands_end() const { return MemRefsEnd; } - bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + using mmo_iterator = ArrayRef::const_iterator; - /// Assign this MachineSDNodes's memory reference descriptor - /// list. This does not transfer ownership. - void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { - for (mmo_iterator MMI = NewMemRefs, MME = NewMemRefsEnd; MMI != MME; ++MMI) - assert(*MMI && "Null mem ref detected!"); - MemRefs = NewMemRefs; - MemRefsEnd = NewMemRefsEnd; + ArrayRef memoperands() const { + // Special case the common cases. + if (NumMemRefs == 0) + return {}; + if (NumMemRefs == 1) + return makeArrayRef(MemRefs.getAddrOfPtr1(), 1); + + // Otherwise we have an actual array. + return makeArrayRef(MemRefs.get(), NumMemRefs); + } + mmo_iterator memoperands_begin() const { return memoperands().begin(); } + mmo_iterator memoperands_end() const { return memoperands().end(); } + bool memoperands_empty() const { return memoperands().empty(); } + + /// Clear out the memory reference descriptor list. + void clearMemRefs() { + MemRefs = nullptr; + NumMemRefs = 0; } static bool classof(const SDNode *N) { @@ -2405,17 +2473,32 @@ namespace ISD { cast(N)->getAddressingMode() == ISD::UNINDEXED; } + /// Return true if the node is a math/logic binary operator. This corresponds + /// to the IR function of the same name. + inline bool isBinaryOp(const SDNode *N) { + auto Op = N->getOpcode(); + return (Op == ISD::ADD || Op == ISD::SUB || Op == ISD::MUL || + Op == ISD::AND || Op == ISD::OR || Op == ISD::XOR || + Op == ISD::SHL || Op == ISD::SRL || Op == ISD::SRA || + Op == ISD::SDIV || Op == ISD::UDIV || Op == ISD::SREM || + Op == ISD::UREM || Op == ISD::FADD || Op == ISD::FSUB || + Op == ISD::FMUL || Op == ISD::FDIV || Op == ISD::FREM); + } + /// Attempt to match a unary predicate against a scalar/splat constant or /// every element of a constant BUILD_VECTOR. + /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. bool matchUnaryPredicate(SDValue Op, - std::function Match); + std::function Match, + bool AllowUndefs = false); /// Attempt to match a binary predicate against a pair of scalar/splat /// constants or every element of a pair of constant BUILD_VECTORs. + /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. bool matchBinaryPredicate( SDValue LHS, SDValue RHS, - std::function Match); - + std::function Match, + bool AllowUndefs = false); } // end namespace ISD } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h index 334267d9828..8c8a7be459f 100644 --- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -413,8 +413,14 @@ class raw_ostream; /// Returns the base index for the given instruction. SlotIndex getInstructionIndex(const MachineInstr &MI) const { // Instructions inside a bundle have the same number as the bundle itself. - const MachineInstr &BundleStart = *getBundleStart(MI.getIterator()); - Mi2IndexMap::const_iterator itr = mi2iMap.find(&BundleStart); + auto BundleStart = getBundleStart(MI.getIterator()); + auto BundleEnd = getBundleEnd(MI.getIterator()); + // Use the first non-debug instruction in the bundle to get SlotIndex. + const MachineInstr &BundleNonDebug = + *skipDebugInstructionsForward(BundleStart, BundleEnd); + assert(!BundleNonDebug.isDebugInstr() && + "Could not use a debug instruction to query mi2iMap."); + Mi2IndexMap::const_iterator itr = mi2iMap.find(&BundleNonDebug); assert(itr != mi2iMap.end() && "Instruction not found in maps."); return itr->second; } @@ -442,7 +448,7 @@ class raw_ostream; /// MI is not required to have an index. SlotIndex getIndexBefore(const MachineInstr &MI) const { const MachineBasicBlock *MBB = MI.getParent(); - assert(MBB && "MI must be inserted inna basic block"); + assert(MBB && "MI must be inserted in a basic block"); MachineBasicBlock::const_iterator I = MI, B = MBB->begin(); while (true) { if (I == B) @@ -459,7 +465,7 @@ class raw_ostream; /// MI is not required to have an index. SlotIndex getIndexAfter(const MachineInstr &MI) const { const MachineBasicBlock *MBB = MI.getParent(); - assert(MBB && "MI must be inserted inna basic block"); + assert(MBB && "MI must be inserted in a basic block"); MachineBasicBlock::const_iterator I = MI, E = MBB->end(); while (true) { ++I; @@ -674,7 +680,7 @@ class raw_ostream; idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); renumberIndexes(newItr); - llvm::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); + llvm::sort(idx2MBBMap, Idx2MBBCompare()); } /// Free the resources that were required to maintain a SlotIndex. diff --git a/contrib/llvm/include/llvm/CodeGen/StackMaps.h b/contrib/llvm/include/llvm/CodeGen/StackMaps.h index e584a4136e4..8be9ae37855 100644 --- a/contrib/llvm/include/llvm/CodeGen/StackMaps.h +++ b/contrib/llvm/include/llvm/CodeGen/StackMaps.h @@ -236,25 +236,6 @@ public: FnInfos.clear(); } - /// Generate a stackmap record for a stackmap instruction. - /// - /// MI must be a raw STACKMAP, not a PATCHPOINT. - void recordStackMap(const MachineInstr &MI); - - /// Generate a stackmap record for a patchpoint instruction. - void recordPatchPoint(const MachineInstr &MI); - - /// Generate a stackmap record for a statepoint instruction. - void recordStatepoint(const MachineInstr &MI); - - /// If there is any stack map data, create a stack map section and serialize - /// the map info into it. This clears the stack map data structures - /// afterwards. - void serializeToStackMapSection(); - -private: - static const char *WSMP; - using LocationVec = SmallVector; using LiveOutVec = SmallVector; using ConstantPool = MapVector; @@ -283,6 +264,31 @@ private: using FnInfoMap = MapVector; using CallsiteInfoList = std::vector; + /// Generate a stackmap record for a stackmap instruction. + /// + /// MI must be a raw STACKMAP, not a PATCHPOINT. + void recordStackMap(const MachineInstr &MI); + + /// Generate a stackmap record for a patchpoint instruction. + void recordPatchPoint(const MachineInstr &MI); + + /// Generate a stackmap record for a statepoint instruction. + void recordStatepoint(const MachineInstr &MI); + + /// If there is any stack map data, create a stack map section and serialize + /// the map info into it. This clears the stack map data structures + /// afterwards. + void serializeToStackMapSection(); + + /// Get call site info. + CallsiteInfoList &getCSInfos() { return CSInfos; } + + /// Get function info. + FnInfoMap &getFnInfos() { return FnInfos; } + +private: + static const char *WSMP; + AsmPrinter &AP; CallsiteInfoList CSInfos; ConstantPool ConstPool; diff --git a/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h index f8effee998e..b4d1da94143 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -207,8 +207,11 @@ public: return false; } - /// Return true if the target needs to disable frame pointer elimination. - virtual bool noFramePointerElim(const MachineFunction &MF) const; + /// Return true if the target wants to keep the frame pointer regardless of + /// the function attribute "frame-pointer". + virtual bool keepFramePointer(const MachineFunction &MF) const { + return false; + } /// hasFP - Return true if the specified function should have a dedicated /// frame pointer register. For most targets this is true only if the function diff --git a/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h index b5bc561d834..961b90e9bc1 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -246,14 +246,14 @@ public: } /// 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. + /// return true along with the FrameIndices of the loaded stack slot and the + /// machine mem operands containing the reference. /// If not, return false. Unlike isLoadFromStackSlot, this returns true for /// any instructions that loads from the stack. This is just a hint, as some /// cases may be missed. - virtual bool hasLoadFromStackSlot(const MachineInstr &MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const; + virtual bool hasLoadFromStackSlot( + const MachineInstr &MI, + SmallVectorImpl &Accesses) const; /// If the specified machine instruction is a direct /// store to a stack slot, return the virtual or physical register number of @@ -284,14 +284,14 @@ public: } /// 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. + /// return true along with the FrameIndices of the loaded stack slot and the + /// machine mem operands containing the reference. /// If not, return false. Unlike isStoreToStackSlot, /// this returns true for any instructions that stores to the /// stack. This is just a hint, as some cases may be missed. - virtual bool hasStoreToStackSlot(const MachineInstr &MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const; + virtual bool hasStoreToStackSlot( + const MachineInstr &MI, + SmallVectorImpl &Accesses) const; /// Return true if the specified machine instruction /// is a copy of one stack slot to another and has no other effect. @@ -846,15 +846,33 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!"); } +protected: + /// Target-dependent implemenation for IsCopyInstr. /// If the specific machine instruction is a instruction that moves/copies /// value from one register to another register return true along with /// @Source machine operand and @Destination machine operand. - virtual bool isCopyInstr(const MachineInstr &MI, - const MachineOperand *&SourceOpNum, - const MachineOperand *&Destination) const { + virtual bool isCopyInstrImpl(const MachineInstr &MI, + const MachineOperand *&Source, + const MachineOperand *&Destination) const { return false; } +public: + /// If the specific machine instruction is a instruction that moves/copies + /// value from one register to another register return true along with + /// @Source machine operand and @Destination machine operand. + /// For COPY-instruction the method naturally returns true, for all other + /// instructions the method calls target-dependent implementation. + bool isCopyInstr(const MachineInstr &MI, const MachineOperand *&Source, + const MachineOperand *&Destination) const { + if (MI.isCopy()) { + Destination = &MI.getOperand(0); + Source = &MI.getOperand(1); + return true; + } + return isCopyInstrImpl(MI, Source, Destination); + } + /// Store the specified register of the given register class to the specified /// stack frame index. The store instruction is to be added to the given /// machine basic block before the specified machine instruction. If isKill @@ -1063,7 +1081,7 @@ public: /// getAddressSpaceForPseudoSourceKind - Given the kind of memory /// (e.g. stack) the target returns the corresponding address space. virtual unsigned - getAddressSpaceForPseudoSourceKind(PseudoSourceValue::PSVKind Kind) const { + getAddressSpaceForPseudoSourceKind(unsigned Kind) const { return 0; } @@ -1118,11 +1136,11 @@ public: return false; } - /// Get the base register and byte offset of an instruction that reads/writes + /// Get the base operand and byte offset of an instruction that reads/writes /// memory. - virtual bool getMemOpBaseRegImmOfs(MachineInstr &MemOp, unsigned &BaseReg, - int64_t &Offset, - const TargetRegisterInfo *TRI) const { + virtual bool getMemOperandWithOffset(MachineInstr &MI, + MachineOperand *&BaseOp, int64_t &Offset, + const TargetRegisterInfo *TRI) const { return false; } @@ -1146,8 +1164,8 @@ public: /// or /// DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI)); /// to TargetPassConfig::createMachineScheduler() to have an effect. - virtual bool shouldClusterMemOps(MachineInstr &FirstLdSt, unsigned BaseReg1, - MachineInstr &SecondLdSt, unsigned BaseReg2, + virtual bool shouldClusterMemOps(MachineOperand &BaseOp1, + MachineOperand &BaseOp2, unsigned NumLoads) const { llvm_unreachable("target did not implement shouldClusterMemOps()"); } @@ -1617,10 +1635,11 @@ public: "Target didn't implement TargetInstrInfo::getOutliningType!"); } - /// Returns target-defined flags defining properties of the MBB for - /// the outliner. - virtual unsigned getMachineOutlinerMBBFlags(MachineBasicBlock &MBB) const { - return 0x0; + /// Optional target hook that returns true if \p MBB is safe to outline from, + /// and returns any target-specific information in \p Flags. + virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, + unsigned &Flags) const { + return true; } /// Insert a custom frame for outlined functions. diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLowering.h b/contrib/llvm/include/llvm/CodeGen/TargetLowering.h index 40540bd6e1f..23dbaac03eb 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetLowering.h @@ -29,7 +29,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/DivergenceAnalysis.h" +#include "llvm/Analysis/LegacyDivergenceAnalysis.h" #include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/RuntimeLibcalls.h" @@ -163,6 +163,7 @@ public: LLOnly, // Expand the (load) instruction into just a load-linked, which has // greater atomic guarantees than a normal load. CmpXChg, // Expand the instruction into cmpxchg; used by at least X86. + MaskedIntrinsic, // Use a target-specific intrinsic for the LL/SC loop. }; /// Enum that specifies when a multiplication should be expanded. @@ -268,6 +269,14 @@ public: return true; } + /// Return true if it is profitable to convert a select of FP constants into + /// a constant pool load whose address depends on the select condition. The + /// parameter may be used to differentiate a select with FP compare from + /// integer compare. + virtual bool reduceSelectOfFPConstantLoads(bool IsFPSetCC) const { + return true; + } + /// Return true if multiple condition registers are available. bool hasMultipleConditionRegisters() const { return HasMultipleConditionRegisters; @@ -278,7 +287,7 @@ public: /// Return the preferred vector type legalization action. virtual TargetLoweringBase::LegalizeTypeAction - getPreferredVectorAction(EVT VT) const { + getPreferredVectorAction(MVT VT) const { // The default action for one element vectors is to scalarize if (VT.getVectorNumElements() == 1) return TypeScalarizeVector; @@ -545,6 +554,12 @@ public: return false; } + /// Return true if inserting a scalar into a variable element of an undef + /// vector is more efficiently handled by splatting the scalar instead. + virtual bool shouldSplatInsEltVarIndex(EVT) const { + return false; + } + /// Return true if target supports floating point exceptions. bool hasFloatingPointExceptions() const { return HasFloatingPointExceptions; @@ -790,6 +805,38 @@ public: return OpActions[(unsigned)VT.getSimpleVT().SimpleTy][Op]; } + /// Custom method defined by each target to indicate if an operation which + /// may require a scale is supported natively by the target. + /// If not, the operation is illegal. + virtual bool isSupportedFixedPointOperation(unsigned Op, EVT VT, + unsigned Scale) const { + return false; + } + + /// Some fixed point operations may be natively supported by the target but + /// only for specific scales. This method allows for checking + /// if the width is supported by the target for a given operation that may + /// depend on scale. + LegalizeAction getFixedPointOperationAction(unsigned Op, EVT VT, + unsigned Scale) const { + auto Action = getOperationAction(Op, VT); + if (Action != Legal) + return Action; + + // This operation is supported in this type but may only work on specific + // scales. + bool Supported; + switch (Op) { + default: + llvm_unreachable("Unexpected fixed point operation."); + case ISD::SMULFIX: + Supported = isSupportedFixedPointOperation(Op, VT, Scale); + break; + } + + return Supported ? Action : Expand; + } + LegalizeAction getStrictFPOperationAction(unsigned Op, EVT VT) const { unsigned EqOpc; switch (Op) { @@ -798,6 +845,7 @@ public: case ISD::STRICT_FSUB: EqOpc = ISD::FSUB; break; case ISD::STRICT_FMUL: EqOpc = ISD::FMUL; break; case ISD::STRICT_FDIV: EqOpc = ISD::FDIV; break; + case ISD::STRICT_FREM: EqOpc = ISD::FREM; break; case ISD::STRICT_FSQRT: EqOpc = ISD::FSQRT; break; case ISD::STRICT_FPOW: EqOpc = ISD::FPOW; break; case ISD::STRICT_FPOWI: EqOpc = ISD::FPOWI; break; @@ -811,6 +859,12 @@ public: case ISD::STRICT_FLOG2: EqOpc = ISD::FLOG2; break; case ISD::STRICT_FRINT: EqOpc = ISD::FRINT; break; case ISD::STRICT_FNEARBYINT: EqOpc = ISD::FNEARBYINT; break; + case ISD::STRICT_FMAXNUM: EqOpc = ISD::FMAXNUM; break; + case ISD::STRICT_FMINNUM: EqOpc = ISD::FMINNUM; break; + case ISD::STRICT_FCEIL: EqOpc = ISD::FCEIL; break; + case ISD::STRICT_FFLOOR: EqOpc = ISD::FFLOOR; break; + case ISD::STRICT_FROUND: EqOpc = ISD::FROUND; break; + case ISD::STRICT_FTRUNC: EqOpc = ISD::FTRUNC; break; } auto Action = getOperationAction(EqOpc, VT); @@ -1199,13 +1253,15 @@ public: /// reduce runtime. virtual bool ShouldShrinkFPConstant(EVT) const { return true; } - // Return true if it is profitable to reduce the given load node to a smaller - // type. - // - // e.g. (i16 (trunc (i32 (load x))) -> i16 load x should be performed - virtual bool shouldReduceLoadWidth(SDNode *Load, - ISD::LoadExtType ExtTy, + /// Return true if it is profitable to reduce a load to a smaller type. + /// Example: (i16 (trunc (i32 (load x))) -> i16 load x + virtual bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT) const { + // By default, assume that it is cheaper to extract a subvector from a wide + // vector load rather than creating multiple narrow vector loads. + if (NewVT.isVector() && !Load->hasOneUse()) + return false; + return true; } @@ -1428,6 +1484,12 @@ public: return PrefLoopAlignment; } + /// Should loops be aligned even when the function is marked OptSize (but not + /// MinSize). + virtual bool alignLoopsWithOptSize() const { + return false; + } + /// If the target has a standard location for the stack protector guard, /// returns the address of that location. Otherwise, returns nullptr. /// DEPRECATED: please override useLoadStackGuardNode and customize @@ -1549,6 +1611,26 @@ public: llvm_unreachable("Store conditional unimplemented on this target"); } + /// Perform a masked atomicrmw using a target-specific intrinsic. This + /// represents the core LL/SC loop which will be lowered at a late stage by + /// the backend. + virtual Value *emitMaskedAtomicRMWIntrinsic(IRBuilder<> &Builder, + AtomicRMWInst *AI, + Value *AlignedAddr, Value *Incr, + Value *Mask, Value *ShiftAmt, + AtomicOrdering Ord) const { + llvm_unreachable("Masked atomicrmw expansion unimplemented on this target"); + } + + /// Perform a masked cmpxchg using a target-specific intrinsic. This + /// represents the core LL/SC loop which will be lowered at a late stage by + /// the backend. + virtual Value *emitMaskedAtomicCmpXchgIntrinsic( + IRBuilder<> &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, + Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const { + llvm_unreachable("Masked cmpxchg expansion unimplemented on this target"); + } + /// Inserts in the IR a target-specific intrinsic specifying a fence. /// It is called by AtomicExpandPass before expanding an /// AtomicRMW/AtomicCmpXchg/AtomicStore/AtomicLoad @@ -1625,11 +1707,11 @@ public: return AtomicExpansionKind::None; } - /// Returns true if the given atomic cmpxchg should be expanded by the - /// IR-level AtomicExpand pass into a load-linked/store-conditional sequence - /// (through emitLoadLinked() and emitStoreConditional()). - virtual bool shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const { - return false; + /// Returns how the given atomic cmpxchg should be expanded by the IR-level + /// AtomicExpand pass. + virtual AtomicExpansionKind + shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const { + return AtomicExpansionKind::None; } /// Returns how the IR-level AtomicExpand pass should expand the given @@ -1687,6 +1769,25 @@ public: return false; } + /// Return true if it is profitable to transform an integer + /// multiplication-by-constant into simpler operations like shifts and adds. + /// This may be true if the target does not directly support the + /// multiplication operation for the specified type or the sequence of simpler + /// ops is faster than the multiply. + virtual bool decomposeMulByConstant(EVT VT, SDValue C) const { + return false; + } + + /// Return true if it is more correct/profitable to use strict FP_TO_INT + /// conversion operations - canonicalizing the FP source value instead of + /// converting all cases and then selecting based on value. + /// This may be true if the target throws exceptions for out of bounds + /// conversions or has fast FP CMOV. + virtual bool shouldUseStrictFP_TO_INT(EVT FpVT, EVT IntVT, + bool IsSigned) const { + return false; + } + //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. @@ -2015,6 +2116,14 @@ public: return true; } + /// Return true if the specified immediate is legal for the value input of a + /// store instruction. + virtual bool isLegalStoreImmediate(int64_t Value) const { + // Default implementation assumes that at least 0 works since it is likely + // that a zero register exists or a zero immediate is allowed. + return Value == 0; + } + /// Return true if it's significantly cheaper to shift a vector by a uniform /// scalar than by an amount which will vary across each lane. On x86, for /// example, there is a "psllw" instruction for the former case, but no simple @@ -2046,10 +2155,12 @@ public: case ISD::UADDO: case ISD::ADDC: case ISD::ADDE: + case ISD::SADDSAT: + case ISD::UADDSAT: case ISD::FMINNUM: case ISD::FMAXNUM: - case ISD::FMINNAN: - case ISD::FMAXNAN: + case ISD::FMINIMUM: + case ISD::FMAXIMUM: return true; default: return false; } @@ -2153,6 +2264,12 @@ public: return false; } + /// Return true if sign-extension from FromTy to ToTy is cheaper than + /// zero-extension. + virtual bool isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const { + return false; + } + /// Return true if the target supplies and combines to a paired load /// two loaded values of type LoadedType next to each other in memory. /// RequiredAlignment gives the minimal alignment constraints that must be met @@ -2292,6 +2409,12 @@ public: return false; } + /// Try to convert an extract element of a vector binary operation into an + /// extract element followed by a scalar operation. + virtual bool shouldScalarizeBinop(SDValue VecOp) const { + return false; + } + // Return true if it is profitable to use a scalar input to a BUILD_VECTOR // even if the vector itself has multiple uses. virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const { @@ -2648,7 +2771,7 @@ public: virtual bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, - DivergenceAnalysis *DA) const { + LegacyDivergenceAnalysis *DA) const { return false; } @@ -2774,36 +2897,33 @@ public: bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded, TargetLoweringOpt &TLO) const; - /// Helper for SimplifyDemandedBits that can simplify an operation with - /// multiple uses. This function simplifies operand \p OpIdx of \p User and - /// then updates \p User with the simplified version. No other uses of - /// \p OpIdx are updated. If \p User is the only user of \p OpIdx, this - /// function behaves exactly like function SimplifyDemandedBits declared - /// below except that it also updates the DAG by calling - /// DCI.CommitTargetLoweringOpt. - bool SimplifyDemandedBits(SDNode *User, unsigned OpIdx, const APInt &Demanded, - DAGCombinerInfo &DCI, TargetLoweringOpt &TLO) const; - - /// Look at Op. At this point, we know that only the DemandedMask bits of the + /// Look at Op. At this point, we know that only the DemandedBits bits of the /// result of Op are ever used downstream. If we can use this information to /// simplify Op, create a new simplified DAG node and return true, returning /// the original and new nodes in Old and New. Otherwise, analyze the /// expression and return a mask of KnownOne and KnownZero bits for the /// expression (used to simplify the caller). The KnownZero/One bits may only - /// be accurate for those bits in the DemandedMask. + /// be accurate for those bits in the Demanded masks. /// \p AssumeSingleUse When this parameter is true, this function will /// attempt to simplify \p Op even if there are multiple uses. /// Callers are responsible for correctly updating the DAG based on the /// results of this function, because simply replacing replacing TLO.Old /// with TLO.New will be incorrect when this parameter is true and TLO.Old /// has multiple uses. - bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, - KnownBits &Known, - TargetLoweringOpt &TLO, + bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, + const APInt &DemandedElts, KnownBits &Known, + TargetLoweringOpt &TLO, unsigned Depth = 0, + bool AssumeSingleUse = false) const; + + /// Helper wrapper around SimplifyDemandedBits, demanding all elements. + /// Adds Op back to the worklist upon success. + bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, + KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth = 0, bool AssumeSingleUse = false) const; - /// Helper wrapper around SimplifyDemandedBits + /// Helper wrapper around SimplifyDemandedBits. + /// Adds Op back to the worklist upon success. bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, DAGCombinerInfo &DCI) const; @@ -2826,7 +2946,8 @@ public: TargetLoweringOpt &TLO, unsigned Depth = 0, bool AssumeSingleUse = false) const; - /// Helper wrapper around SimplifyDemandedVectorElts + /// Helper wrapper around SimplifyDemandedVectorElts. + /// Adds Op back to the worklist upon success. bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedElts, APInt &KnownUndef, APInt &KnownZero, DAGCombinerInfo &DCI) const; @@ -2863,11 +2984,30 @@ public: /// elements, returning true on success. Otherwise, analyze the expression and /// return a mask of KnownUndef and KnownZero elements for the expression /// (used to simplify the caller). The KnownUndef/Zero elements may only be - /// accurate for those bits in the DemandedMask + /// accurate for those bits in the DemandedMask. virtual bool SimplifyDemandedVectorEltsForTargetNode( SDValue Op, const APInt &DemandedElts, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth = 0) const; + /// Attempt to simplify any target nodes based on the demanded bits/elts, + /// returning true on success. Otherwise, analyze the + /// expression and return a mask of KnownOne and KnownZero bits for the + /// expression (used to simplify the caller). The KnownZero/One bits may only + /// be accurate for those bits in the Demanded masks. + virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, + const APInt &DemandedBits, + const APInt &DemandedElts, + KnownBits &Known, + TargetLoweringOpt &TLO, + unsigned Depth = 0) const; + + /// If \p SNaN is false, \returns true if \p Op is known to never be any + /// NaN. If \p sNaN is true, returns if \p Op is known to never be a signaling + /// NaN. + virtual bool isKnownNeverNaNForTargetNode(SDValue Op, + const SelectionDAG &DAG, + bool SNaN = false, + unsigned Depth = 0) const; struct DAGCombinerInfo { void *DC; // The DAG Combiner object. CombineLevel Level; @@ -2935,12 +3075,25 @@ public: /// virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; - /// Return true if it is profitable to move a following shift through this - // node, adjusting any immediate operands as necessary to preserve semantics. - // This transformation may not be desirable if it disrupts a particularly - // auspicious target-specific tree (e.g. bitfield extraction in AArch64). - // By default, it returns true. - virtual bool isDesirableToCommuteWithShift(const SDNode *N) const { + /// Return true if it is profitable to move this shift by a constant amount + /// though its operand, adjusting any immediate operands as necessary to + /// preserve semantics. This transformation may not be desirable if it + /// disrupts a particularly auspicious target-specific tree (e.g. bitfield + /// extraction in AArch64). By default, it returns true. + /// + /// @param N the shift node + /// @param Level the current DAGCombine legalization level. + virtual bool isDesirableToCommuteWithShift(const SDNode *N, + CombineLevel Level) const { + return true; + } + + /// Return true if it is profitable to fold a pair of shifts into a mask. + /// This is usually true on most targets. But some targets, like Thumb1, + /// have immediate shift instructions, but no immediate "and" instruction; + /// this makes the fold unprofitable. + virtual bool shouldFoldShiftPairToMask(const SDNode *N, + CombineLevel Level) const { return true; } @@ -3488,11 +3641,9 @@ public: //===--------------------------------------------------------------------===// // Div utility functions // - SDValue BuildSDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, - bool IsAfterLegalization, + SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, SmallVectorImpl &Created) const; - SDValue BuildUDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, - bool IsAfterLegalization, + SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, SmallVectorImpl &Created) const; /// Targets may override this function to provide custom SDIV lowering for @@ -3584,12 +3735,68 @@ public: SDValue LL = SDValue(), SDValue LH = SDValue(), SDValue RL = SDValue(), SDValue RH = SDValue()) const; + /// Expand funnel shift. + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandFunnelShift(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + + /// Expand rotations. + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandROT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + /// Expand float(f32) to SINT(i64) conversion /// \param N Node to expand /// \param Result output after conversion /// \returns True, if the expansion was successful, false otherwise bool expandFP_TO_SINT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + /// Expand float to UINT conversion + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandFP_TO_UINT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + + /// Expand UINT(i64) to double(f64) conversion + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandUINT_TO_FP(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + + /// Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs. + SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const; + + /// Expand CTPOP nodes. Expands vector/scalar CTPOP nodes, + /// vector nodes can only succeed if all operations are legal/custom. + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandCTPOP(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + + /// Expand CTLZ/CTLZ_ZERO_UNDEF nodes. Expands vector/scalar CTLZ nodes, + /// vector nodes can only succeed if all operations are legal/custom. + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandCTLZ(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + + /// Expand CTTZ/CTTZ_ZERO_UNDEF nodes. Expands vector/scalar CTTZ nodes, + /// vector nodes can only succeed if all operations are legal/custom. + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandCTTZ(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + + /// Expand ABS nodes. Expands vector/scalar ABS nodes, + /// vector nodes can only succeed if all operations are legal/custom. + /// (ABS x) -> (XOR (ADD x, (SRA x, type_size)), (SRA x, type_size)) + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandABS(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; + /// Turn load of vector type into a load of the individual elements. /// \param LD load to expand /// \returns MERGE_VALUEs of the scalar loads with their chains. @@ -3627,6 +3834,15 @@ public: SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index) const; + /// Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT. This + /// method accepts integers as its arguments. + SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const; + + /// Method for building the DAG expansion of ISD::SMULFIX. This method accepts + /// integers as its arguments. + SDValue getExpandedFixedPointMultiplication(SDNode *Node, + SelectionDAG &DAG) const; + //===--------------------------------------------------------------------===// // Instruction Emitting Hooks // diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index f5c7fc824ab..052d1f8bc68 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -90,6 +90,8 @@ public: const MCExpr *lowerRelativeReference(const GlobalValue *LHS, const GlobalValue *RHS, const TargetMachine &TM) const override; + + MCSection *getSectionForCommandLines() const override; }; class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { diff --git a/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h b/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h index 8f5c9cb8c3f..3288711a335 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h @@ -90,6 +90,19 @@ private: AnalysisID StartAfter = nullptr; AnalysisID StopBefore = nullptr; AnalysisID StopAfter = nullptr; + + unsigned StartBeforeInstanceNum = 0; + unsigned StartBeforeCount = 0; + + unsigned StartAfterInstanceNum = 0; + unsigned StartAfterCount = 0; + + unsigned StopBeforeInstanceNum = 0; + unsigned StopBeforeCount = 0; + + unsigned StopAfterInstanceNum = 0; + unsigned StopAfterCount = 0; + bool Started = true; bool Stopped = false; bool AddingMachinePasses = false; @@ -145,13 +158,13 @@ public: CodeGenOpt::Level getOptLevel() const; - /// Describe the status of the codegen - /// pipeline set by this target pass config. - /// Having a limited codegen pipeline means that options - /// have been used to restrict what codegen is doing. - /// In particular, that means that codegen won't emit - /// assembly code. - bool hasLimitedCodeGenPipeline() const; + /// Returns true if one of the `-start-after`, `-start-before`, `-stop-after` + /// or `-stop-before` options is set. + static bool hasLimitedCodeGenPipeline(); + + /// Returns true if none of the `-stop-before` and `-stop-after` options is + /// set. + static bool willCompleteCodeGenPipeline(); /// If hasLimitedCodeGenPipeline is true, this method /// returns a string with the name of the options, separated @@ -159,13 +172,6 @@ public: std::string getLimitedCodeGenPipelineReason(const char *Separator = "/") const; - /// Check if the codegen pipeline is limited in such a way that it - /// won't be complete. When the codegen pipeline is not complete, - /// this means it may not be possible to generate assembly from it. - bool willCompleteCodeGenPipeline() const { - return !hasLimitedCodeGenPipeline() || (!StopAfter && !StopBefore); - } - void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } bool getEnableTailMerge() const { return EnableTailMerge; } diff --git a/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h index 55a8ba630a5..0fbff313765 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -510,6 +510,13 @@ public: /// markSuperRegs() and checkAllSuperRegsMarked() in this case. virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + /// Returns false if we can't guarantee that Physreg, specified as an IR asm + /// clobber constraint, will be preserved across the statement. + virtual bool isAsmClobberable(const MachineFunction &MF, + unsigned PhysReg) const { + return true; + } + /// Returns true if PhysReg is unallocatable and constant throughout the /// function. Used by MachineRegisterInfo::isConstantPhysReg(). virtual bool isConstantPhysReg(unsigned PhysReg) const { return false; } @@ -817,13 +824,6 @@ public: // Do nothing. } - /// The creation of multiple copy hints have been implemented in - /// weightCalcHelper(), but since this affects so many tests for many - /// targets, this is temporarily disabled per default. THIS SHOULD BE - /// "GENERAL GOODNESS" and hopefully all targets will update their tests - /// and enable this soon. This hook should then be removed. - virtual bool enableMultipleCopyHints() const { return false; } - /// Allow the target to reverse allocation order of local live ranges. This /// will generally allocate shorter local live ranges first. For targets with /// many registers, this could reduce regalloc compile time by a large diff --git a/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h index 227e591f5a7..968e4c4b810 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_TARGETSUBTARGETINFO_H #define LLVM_CODEGEN_TARGETSUBTARGETINFO_H +#include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -144,6 +145,43 @@ public: return 0; } + /// Returns true if MI is a dependency breaking zero-idiom instruction for the + /// subtarget. + /// + /// This function also sets bits in Mask related to input operands that + /// are not in a data dependency relationship. There is one bit for each + /// machine operand; implicit operands follow explicit operands in the bit + /// representation used for Mask. An empty (i.e. a mask with all bits + /// cleared) means: data dependencies are "broken" for all the explicit input + /// machine operands of MI. + virtual bool isZeroIdiom(const MachineInstr *MI, APInt &Mask) const { + return false; + } + + /// Returns true if MI is a dependency breaking instruction for the subtarget. + /// + /// Similar in behavior to `isZeroIdiom`. However, it knows how to identify + /// all dependency breaking instructions (i.e. not just zero-idioms). + /// + /// As for `isZeroIdiom`, this method returns a mask of "broken" dependencies. + /// (See method `isZeroIdiom` for a detailed description of Mask). + virtual bool isDependencyBreaking(const MachineInstr *MI, APInt &Mask) const { + return isZeroIdiom(MI, Mask); + } + + /// Returns true if MI is a candidate for move elimination. + /// + /// A candidate for move elimination may be optimized out at register renaming + /// stage. Subtargets can specify the set of optimizable moves by + /// instantiating tablegen class `IsOptimizableRegisterMove` (see + /// llvm/Target/TargetInstrPredicate.td). + /// + /// SubtargetEmitter is responsible for processing all the definitions of class + /// IsOptimizableRegisterMove, and auto-generate an override for this method. + virtual bool isOptimizableRegisterMove(const MachineInstr *MI) const { + return false; + } + /// True if the subtarget should run MachineScheduler after aggressive /// coalescing. /// diff --git a/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h b/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h index 3ad6760d881..219fff988f6 100644 --- a/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h @@ -14,13 +14,15 @@ #ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H #define LLVM_CODEGEN_WASMEHFUNCINFO_H -#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/BasicBlock.h" namespace llvm { +enum EventTag { CPP_EXCEPTION = 0, C_LONGJMP = 1 }; + using BBOrMBB = PointerUnion; struct WasmEHFuncInfo { diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h index 9dbeb438f4a..11ca9ff108d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -45,13 +45,8 @@ public: return RecordData.drop_front(sizeof(RecordPrefix)); } - Optional hash() const { return Hash; } - - void setHash(uint32_t Value) { Hash = Value; } - Kind Type; ArrayRef RecordData; - Optional Hash; }; template struct RemappedRecord { diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index 4ce9f68cffd..8e0d9f608e9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -231,6 +231,8 @@ enum class FrameProcedureOptions : uint32_t { Inlined = 0x00000800, StrictSecurityChecks = 0x00001000, SafeBuffers = 0x00002000, + EncodedLocalBasePointerMask = 0x0000C000, + EncodedParamBasePointerMask = 0x00030000, ProfileGuidedOptimization = 0x00040000, ValidProfileCounts = 0x00080000, OptimizedForSpeed = 0x00100000, @@ -356,7 +358,9 @@ enum class PointerOptions : uint32_t { Const = 0x00000400, Unaligned = 0x00000800, Restrict = 0x00001000, - WinRTSmartPointer = 0x00080000 + WinRTSmartPointer = 0x00080000, + LValueRefThisPointer = 0x00100000, + RValueRefThisPointer = 0x00200000 }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(PointerOptions) @@ -510,6 +514,19 @@ enum class RegisterId : uint16_t { #undef CV_REGISTER }; +/// Two-bit value indicating which register is the designated frame pointer +/// register. Appears in the S_FRAMEPROC record flags. +enum class EncodedFramePtrReg : uint8_t { + None = 0, + StackPtr = 1, + FramePtr = 2, + BasePtr = 3, +}; + +RegisterId decodeFramePtrReg(EncodedFramePtrReg EncodedReg, CPUType CPU); + +EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU); + /// These values correspond to the THUNK_ORDINAL enumeration. enum class ThunkOrdinal : uint8_t { Standard, diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h index 586a720ce6e..d4615d02220 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h @@ -24,23 +24,32 @@ enum class cv_error_code { no_records, unknown_member_record, }; +} // namespace codeview +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} // namespace std + +namespace llvm { +namespace codeview { +const std::error_category &CVErrorCategory(); + +inline std::error_code make_error_code(cv_error_code E) { + return std::error_code(static_cast(E), CVErrorCategory()); +} /// Base class for errors originating when parsing raw PDB files -class CodeViewError : public ErrorInfo { +class CodeViewError : public ErrorInfo { public: + using ErrorInfo::ErrorInfo; // inherit constructors + CodeViewError(const Twine &S) : ErrorInfo(S, cv_error_code::unspecified) {} static char ID; - CodeViewError(cv_error_code C); - CodeViewError(const std::string &Context); - CodeViewError(cv_error_code C, const std::string &Context); - - void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - cv_error_code Code; }; -} -} + +} // namespace codeview +} // namespace llvm + #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def index 6da8893bd61..fdfcf4d53a2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def @@ -18,251 +18,342 @@ // This currently only contains the "register subset shared by all processor // types" (ERR etc.) and the x86 registers. -CV_REGISTER(CVRegERR, 30000) -CV_REGISTER(CVRegTEB, 30001) -CV_REGISTER(CVRegTIMER, 30002) -CV_REGISTER(CVRegEFAD1, 30003) -CV_REGISTER(CVRegEFAD2, 30004) -CV_REGISTER(CVRegEFAD3, 30005) -CV_REGISTER(CVRegVFRAME, 30006) -CV_REGISTER(CVRegHANDLE, 30007) -CV_REGISTER(CVRegPARAMS, 30008) -CV_REGISTER(CVRegLOCALS, 30009) -CV_REGISTER(CVRegTID, 30010) -CV_REGISTER(CVRegENV, 30011) -CV_REGISTER(CVRegCMDLN, 30012) +// Some system headers define macros that conflict with our enums. Every +// compiler supported by LLVM has the push_macro and pop_macro pragmas, so use +// them to avoid the conflict. +#pragma push_macro("CR0") +#pragma push_macro("CR1") +#pragma push_macro("CR2") +#pragma push_macro("CR3") +#pragma push_macro("CR4") -CV_REGISTER(CVRegNONE, 0) -CV_REGISTER(CVRegAL, 1) -CV_REGISTER(CVRegCL, 2) -CV_REGISTER(CVRegDL, 3) -CV_REGISTER(CVRegBL, 4) -CV_REGISTER(CVRegAH, 5) -CV_REGISTER(CVRegCH, 6) -CV_REGISTER(CVRegDH, 7) -CV_REGISTER(CVRegBH, 8) -CV_REGISTER(CVRegAX, 9) -CV_REGISTER(CVRegCX, 10) -CV_REGISTER(CVRegDX, 11) -CV_REGISTER(CVRegBX, 12) -CV_REGISTER(CVRegSP, 13) -CV_REGISTER(CVRegBP, 14) -CV_REGISTER(CVRegSI, 15) -CV_REGISTER(CVRegDI, 16) -CV_REGISTER(CVRegEAX, 17) -CV_REGISTER(CVRegECX, 18) -CV_REGISTER(CVRegEDX, 19) -CV_REGISTER(CVRegEBX, 20) -CV_REGISTER(CVRegESP, 21) -CV_REGISTER(CVRegEBP, 22) -CV_REGISTER(CVRegESI, 23) -CV_REGISTER(CVRegEDI, 24) -CV_REGISTER(CVRegES, 25) -CV_REGISTER(CVRegCS, 26) -CV_REGISTER(CVRegSS, 27) -CV_REGISTER(CVRegDS, 28) -CV_REGISTER(CVRegFS, 29) -CV_REGISTER(CVRegGS, 30) -CV_REGISTER(CVRegIP, 31) -CV_REGISTER(CVRegFLAGS, 32) -CV_REGISTER(CVRegEIP, 33) -CV_REGISTER(CVRegEFLAGS, 34) -CV_REGISTER(CVRegTEMP, 40) -CV_REGISTER(CVRegTEMPH, 41) -CV_REGISTER(CVRegQUOTE, 42) -CV_REGISTER(CVRegPCDR3, 43) -CV_REGISTER(CVRegPCDR4, 44) -CV_REGISTER(CVRegPCDR5, 45) -CV_REGISTER(CVRegPCDR6, 46) -CV_REGISTER(CVRegPCDR7, 47) -CV_REGISTER(CVRegCR0, 80) -CV_REGISTER(CVRegCR1, 81) -CV_REGISTER(CVRegCR2, 82) -CV_REGISTER(CVRegCR3, 83) -CV_REGISTER(CVRegCR4, 84) -CV_REGISTER(CVRegDR0, 90) -CV_REGISTER(CVRegDR1, 91) -CV_REGISTER(CVRegDR2, 92) -CV_REGISTER(CVRegDR3, 93) -CV_REGISTER(CVRegDR4, 94) -CV_REGISTER(CVRegDR5, 95) -CV_REGISTER(CVRegDR6, 96) -CV_REGISTER(CVRegDR7, 97) -CV_REGISTER(CVRegGDTR, 110) -CV_REGISTER(CVRegGDTL, 111) -CV_REGISTER(CVRegIDTR, 112) -CV_REGISTER(CVRegIDTL, 113) -CV_REGISTER(CVRegLDTR, 114) -CV_REGISTER(CVRegTR, 115) +CV_REGISTER(ERR, 30000) +CV_REGISTER(TEB, 30001) +CV_REGISTER(TIMER, 30002) +CV_REGISTER(EFAD1, 30003) +CV_REGISTER(EFAD2, 30004) +CV_REGISTER(EFAD3, 30005) +CV_REGISTER(VFRAME, 30006) +CV_REGISTER(HANDLE, 30007) +CV_REGISTER(PARAMS, 30008) +CV_REGISTER(LOCALS, 30009) +CV_REGISTER(TID, 30010) +CV_REGISTER(ENV, 30011) +CV_REGISTER(CMDLN, 30012) -CV_REGISTER(CVRegPSEUDO1, 116) -CV_REGISTER(CVRegPSEUDO2, 117) -CV_REGISTER(CVRegPSEUDO3, 118) -CV_REGISTER(CVRegPSEUDO4, 119) -CV_REGISTER(CVRegPSEUDO5, 120) -CV_REGISTER(CVRegPSEUDO6, 121) -CV_REGISTER(CVRegPSEUDO7, 122) -CV_REGISTER(CVRegPSEUDO8, 123) -CV_REGISTER(CVRegPSEUDO9, 124) +CV_REGISTER(NONE, 0) +CV_REGISTER(AL, 1) +CV_REGISTER(CL, 2) +CV_REGISTER(DL, 3) +CV_REGISTER(BL, 4) +CV_REGISTER(AH, 5) +CV_REGISTER(CH, 6) +CV_REGISTER(DH, 7) +CV_REGISTER(BH, 8) +CV_REGISTER(AX, 9) +CV_REGISTER(CX, 10) +CV_REGISTER(DX, 11) +CV_REGISTER(BX, 12) +CV_REGISTER(SP, 13) +CV_REGISTER(BP, 14) +CV_REGISTER(SI, 15) +CV_REGISTER(DI, 16) +CV_REGISTER(EAX, 17) +CV_REGISTER(ECX, 18) +CV_REGISTER(EDX, 19) +CV_REGISTER(EBX, 20) +CV_REGISTER(ESP, 21) +CV_REGISTER(EBP, 22) +CV_REGISTER(ESI, 23) +CV_REGISTER(EDI, 24) +CV_REGISTER(ES, 25) +CV_REGISTER(CS, 26) +CV_REGISTER(SS, 27) +CV_REGISTER(DS, 28) +CV_REGISTER(FS, 29) +CV_REGISTER(GS, 30) +CV_REGISTER(IP, 31) +CV_REGISTER(FLAGS, 32) +CV_REGISTER(EIP, 33) +CV_REGISTER(EFLAGS, 34) +CV_REGISTER(TEMP, 40) +CV_REGISTER(TEMPH, 41) +CV_REGISTER(QUOTE, 42) +CV_REGISTER(PCDR3, 43) +CV_REGISTER(PCDR4, 44) +CV_REGISTER(PCDR5, 45) +CV_REGISTER(PCDR6, 46) +CV_REGISTER(PCDR7, 47) +CV_REGISTER(CR0, 80) +CV_REGISTER(CR1, 81) +CV_REGISTER(CR2, 82) +CV_REGISTER(CR3, 83) +CV_REGISTER(CR4, 84) +CV_REGISTER(DR0, 90) +CV_REGISTER(DR1, 91) +CV_REGISTER(DR2, 92) +CV_REGISTER(DR3, 93) +CV_REGISTER(DR4, 94) +CV_REGISTER(DR5, 95) +CV_REGISTER(DR6, 96) +CV_REGISTER(DR7, 97) +CV_REGISTER(GDTR, 110) +CV_REGISTER(GDTL, 111) +CV_REGISTER(IDTR, 112) +CV_REGISTER(IDTL, 113) +CV_REGISTER(LDTR, 114) +CV_REGISTER(TR, 115) -CV_REGISTER(CVRegST0, 128) -CV_REGISTER(CVRegST1, 129) -CV_REGISTER(CVRegST2, 130) -CV_REGISTER(CVRegST3, 131) -CV_REGISTER(CVRegST4, 132) -CV_REGISTER(CVRegST5, 133) -CV_REGISTER(CVRegST6, 134) -CV_REGISTER(CVRegST7, 135) -CV_REGISTER(CVRegCTRL, 136) -CV_REGISTER(CVRegSTAT, 137) -CV_REGISTER(CVRegTAG, 138) -CV_REGISTER(CVRegFPIP, 139) -CV_REGISTER(CVRegFPCS, 140) -CV_REGISTER(CVRegFPDO, 141) -CV_REGISTER(CVRegFPDS, 142) -CV_REGISTER(CVRegISEM, 143) -CV_REGISTER(CVRegFPEIP, 144) -CV_REGISTER(CVRegFPEDO, 145) +CV_REGISTER(PSEUDO1, 116) +CV_REGISTER(PSEUDO2, 117) +CV_REGISTER(PSEUDO3, 118) +CV_REGISTER(PSEUDO4, 119) +CV_REGISTER(PSEUDO5, 120) +CV_REGISTER(PSEUDO6, 121) +CV_REGISTER(PSEUDO7, 122) +CV_REGISTER(PSEUDO8, 123) +CV_REGISTER(PSEUDO9, 124) -CV_REGISTER(CVRegMM0, 146) -CV_REGISTER(CVRegMM1, 147) -CV_REGISTER(CVRegMM2, 148) -CV_REGISTER(CVRegMM3, 149) -CV_REGISTER(CVRegMM4, 150) -CV_REGISTER(CVRegMM5, 151) -CV_REGISTER(CVRegMM6, 152) -CV_REGISTER(CVRegMM7, 153) +CV_REGISTER(ST0, 128) +CV_REGISTER(ST1, 129) +CV_REGISTER(ST2, 130) +CV_REGISTER(ST3, 131) +CV_REGISTER(ST4, 132) +CV_REGISTER(ST5, 133) +CV_REGISTER(ST6, 134) +CV_REGISTER(ST7, 135) +CV_REGISTER(CTRL, 136) +CV_REGISTER(STAT, 137) +CV_REGISTER(TAG, 138) +CV_REGISTER(FPIP, 139) +CV_REGISTER(FPCS, 140) +CV_REGISTER(FPDO, 141) +CV_REGISTER(FPDS, 142) +CV_REGISTER(ISEM, 143) +CV_REGISTER(FPEIP, 144) +CV_REGISTER(FPEDO, 145) -CV_REGISTER(CVRegXMM0, 154) -CV_REGISTER(CVRegXMM1, 155) -CV_REGISTER(CVRegXMM2, 156) -CV_REGISTER(CVRegXMM3, 157) -CV_REGISTER(CVRegXMM4, 158) -CV_REGISTER(CVRegXMM5, 159) -CV_REGISTER(CVRegXMM6, 160) -CV_REGISTER(CVRegXMM7, 161) +CV_REGISTER(MM0, 146) +CV_REGISTER(MM1, 147) +CV_REGISTER(MM2, 148) +CV_REGISTER(MM3, 149) +CV_REGISTER(MM4, 150) +CV_REGISTER(MM5, 151) +CV_REGISTER(MM6, 152) +CV_REGISTER(MM7, 153) -CV_REGISTER(CVRegMXCSR, 211) +CV_REGISTER(XMM0, 154) +CV_REGISTER(XMM1, 155) +CV_REGISTER(XMM2, 156) +CV_REGISTER(XMM3, 157) +CV_REGISTER(XMM4, 158) +CV_REGISTER(XMM5, 159) +CV_REGISTER(XMM6, 160) +CV_REGISTER(XMM7, 161) -CV_REGISTER(CVRegEDXEAX, 212) +CV_REGISTER(MXCSR, 211) -CV_REGISTER(CVRegEMM0L, 220) -CV_REGISTER(CVRegEMM1L, 221) -CV_REGISTER(CVRegEMM2L, 222) -CV_REGISTER(CVRegEMM3L, 223) -CV_REGISTER(CVRegEMM4L, 224) -CV_REGISTER(CVRegEMM5L, 225) -CV_REGISTER(CVRegEMM6L, 226) -CV_REGISTER(CVRegEMM7L, 227) +CV_REGISTER(EDXEAX, 212) -CV_REGISTER(CVRegEMM0H, 228) -CV_REGISTER(CVRegEMM1H, 229) -CV_REGISTER(CVRegEMM2H, 230) -CV_REGISTER(CVRegEMM3H, 231) -CV_REGISTER(CVRegEMM4H, 232) -CV_REGISTER(CVRegEMM5H, 233) -CV_REGISTER(CVRegEMM6H, 234) -CV_REGISTER(CVRegEMM7H, 235) +CV_REGISTER(EMM0L, 220) +CV_REGISTER(EMM1L, 221) +CV_REGISTER(EMM2L, 222) +CV_REGISTER(EMM3L, 223) +CV_REGISTER(EMM4L, 224) +CV_REGISTER(EMM5L, 225) +CV_REGISTER(EMM6L, 226) +CV_REGISTER(EMM7L, 227) -CV_REGISTER(CVRegMM00, 236) -CV_REGISTER(CVRegMM01, 237) -CV_REGISTER(CVRegMM10, 238) -CV_REGISTER(CVRegMM11, 239) -CV_REGISTER(CVRegMM20, 240) -CV_REGISTER(CVRegMM21, 241) -CV_REGISTER(CVRegMM30, 242) -CV_REGISTER(CVRegMM31, 243) -CV_REGISTER(CVRegMM40, 244) -CV_REGISTER(CVRegMM41, 245) -CV_REGISTER(CVRegMM50, 246) -CV_REGISTER(CVRegMM51, 247) -CV_REGISTER(CVRegMM60, 248) -CV_REGISTER(CVRegMM61, 249) -CV_REGISTER(CVRegMM70, 250) -CV_REGISTER(CVRegMM71, 251) +CV_REGISTER(EMM0H, 228) +CV_REGISTER(EMM1H, 229) +CV_REGISTER(EMM2H, 230) +CV_REGISTER(EMM3H, 231) +CV_REGISTER(EMM4H, 232) +CV_REGISTER(EMM5H, 233) +CV_REGISTER(EMM6H, 234) +CV_REGISTER(EMM7H, 235) -CV_REGISTER(CVRegBND0, 396) -CV_REGISTER(CVRegBND1, 397) -CV_REGISTER(CVRegBND2, 398) +CV_REGISTER(MM00, 236) +CV_REGISTER(MM01, 237) +CV_REGISTER(MM10, 238) +CV_REGISTER(MM11, 239) +CV_REGISTER(MM20, 240) +CV_REGISTER(MM21, 241) +CV_REGISTER(MM30, 242) +CV_REGISTER(MM31, 243) +CV_REGISTER(MM40, 244) +CV_REGISTER(MM41, 245) +CV_REGISTER(MM50, 246) +CV_REGISTER(MM51, 247) +CV_REGISTER(MM60, 248) +CV_REGISTER(MM61, 249) +CV_REGISTER(MM70, 250) +CV_REGISTER(MM71, 251) + +CV_REGISTER(BND0, 396) +CV_REGISTER(BND1, 397) +CV_REGISTER(BND2, 398) -CV_REGISTER(CVRegXMM8, 252) -CV_REGISTER(CVRegXMM9, 253) -CV_REGISTER(CVRegXMM10, 254) -CV_REGISTER(CVRegXMM11, 255) -CV_REGISTER(CVRegXMM12, 256) -CV_REGISTER(CVRegXMM13, 257) -CV_REGISTER(CVRegXMM14, 258) -CV_REGISTER(CVRegXMM15, 259) +CV_REGISTER(XMM8, 252) +CV_REGISTER(XMM9, 253) +CV_REGISTER(XMM10, 254) +CV_REGISTER(XMM11, 255) +CV_REGISTER(XMM12, 256) +CV_REGISTER(XMM13, 257) +CV_REGISTER(XMM14, 258) +CV_REGISTER(XMM15, 259) -CV_REGISTER(CVRegSIL, 324) -CV_REGISTER(CVRegDIL, 325) -CV_REGISTER(CVRegBPL, 326) -CV_REGISTER(CVRegSPL, 327) +CV_REGISTER(SIL, 324) +CV_REGISTER(DIL, 325) +CV_REGISTER(BPL, 326) +CV_REGISTER(SPL, 327) -CV_REGISTER(CVRegRAX, 328) -CV_REGISTER(CVRegRBX, 329) -CV_REGISTER(CVRegRCX, 330) -CV_REGISTER(CVRegRDX, 331) -CV_REGISTER(CVRegRSI, 332) -CV_REGISTER(CVRegRDI, 333) -CV_REGISTER(CVRegRBP, 334) -CV_REGISTER(CVRegRSP, 335) +CV_REGISTER(RAX, 328) +CV_REGISTER(RBX, 329) +CV_REGISTER(RCX, 330) +CV_REGISTER(RDX, 331) +CV_REGISTER(RSI, 332) +CV_REGISTER(RDI, 333) +CV_REGISTER(RBP, 334) +CV_REGISTER(RSP, 335) -CV_REGISTER(CVRegR8, 336) -CV_REGISTER(CVRegR9, 337) -CV_REGISTER(CVRegR10, 338) -CV_REGISTER(CVRegR11, 339) -CV_REGISTER(CVRegR12, 340) -CV_REGISTER(CVRegR13, 341) -CV_REGISTER(CVRegR14, 342) -CV_REGISTER(CVRegR15, 343) +CV_REGISTER(R8, 336) +CV_REGISTER(R9, 337) +CV_REGISTER(R10, 338) +CV_REGISTER(R11, 339) +CV_REGISTER(R12, 340) +CV_REGISTER(R13, 341) +CV_REGISTER(R14, 342) +CV_REGISTER(R15, 343) -CV_REGISTER(CVRegR8B, 344) -CV_REGISTER(CVRegR9B, 345) -CV_REGISTER(CVRegR10B, 346) -CV_REGISTER(CVRegR11B, 347) -CV_REGISTER(CVRegR12B, 348) -CV_REGISTER(CVRegR13B, 349) -CV_REGISTER(CVRegR14B, 350) -CV_REGISTER(CVRegR15B, 351) +CV_REGISTER(R8B, 344) +CV_REGISTER(R9B, 345) +CV_REGISTER(R10B, 346) +CV_REGISTER(R11B, 347) +CV_REGISTER(R12B, 348) +CV_REGISTER(R13B, 349) +CV_REGISTER(R14B, 350) +CV_REGISTER(R15B, 351) -CV_REGISTER(CVRegR8W, 352) -CV_REGISTER(CVRegR9W, 353) -CV_REGISTER(CVRegR10W, 354) -CV_REGISTER(CVRegR11W, 355) -CV_REGISTER(CVRegR12W, 356) -CV_REGISTER(CVRegR13W, 357) -CV_REGISTER(CVRegR14W, 358) -CV_REGISTER(CVRegR15W, 359) +CV_REGISTER(R8W, 352) +CV_REGISTER(R9W, 353) +CV_REGISTER(R10W, 354) +CV_REGISTER(R11W, 355) +CV_REGISTER(R12W, 356) +CV_REGISTER(R13W, 357) +CV_REGISTER(R14W, 358) +CV_REGISTER(R15W, 359) -CV_REGISTER(CVRegR8D, 360) -CV_REGISTER(CVRegR9D, 361) -CV_REGISTER(CVRegR10D, 362) -CV_REGISTER(CVRegR11D, 363) -CV_REGISTER(CVRegR12D, 364) -CV_REGISTER(CVRegR13D, 365) -CV_REGISTER(CVRegR14D, 366) -CV_REGISTER(CVRegR15D, 367) +CV_REGISTER(R8D, 360) +CV_REGISTER(R9D, 361) +CV_REGISTER(R10D, 362) +CV_REGISTER(R11D, 363) +CV_REGISTER(R12D, 364) +CV_REGISTER(R13D, 365) +CV_REGISTER(R14D, 366) +CV_REGISTER(R15D, 367) // cvconst.h defines both CV_REG_YMM0 (252) and CV_AMD64_YMM0 (368). Keep the // original prefix to distinguish them. -CV_REGISTER(CVRegAMD64_YMM0, 368) -CV_REGISTER(CVRegAMD64_YMM1, 369) -CV_REGISTER(CVRegAMD64_YMM2, 370) -CV_REGISTER(CVRegAMD64_YMM3, 371) -CV_REGISTER(CVRegAMD64_YMM4, 372) -CV_REGISTER(CVRegAMD64_YMM5, 373) -CV_REGISTER(CVRegAMD64_YMM6, 374) -CV_REGISTER(CVRegAMD64_YMM7, 375) -CV_REGISTER(CVRegAMD64_YMM8, 376) -CV_REGISTER(CVRegAMD64_YMM9, 377) -CV_REGISTER(CVRegAMD64_YMM10, 378) -CV_REGISTER(CVRegAMD64_YMM11, 379) -CV_REGISTER(CVRegAMD64_YMM12, 380) -CV_REGISTER(CVRegAMD64_YMM13, 381) -CV_REGISTER(CVRegAMD64_YMM14, 382) -CV_REGISTER(CVRegAMD64_YMM15, 383) +CV_REGISTER(AMD64_YMM0, 368) +CV_REGISTER(AMD64_YMM1, 369) +CV_REGISTER(AMD64_YMM2, 370) +CV_REGISTER(AMD64_YMM3, 371) +CV_REGISTER(AMD64_YMM4, 372) +CV_REGISTER(AMD64_YMM5, 373) +CV_REGISTER(AMD64_YMM6, 374) +CV_REGISTER(AMD64_YMM7, 375) +CV_REGISTER(AMD64_YMM8, 376) +CV_REGISTER(AMD64_YMM9, 377) +CV_REGISTER(AMD64_YMM10, 378) +CV_REGISTER(AMD64_YMM11, 379) +CV_REGISTER(AMD64_YMM12, 380) +CV_REGISTER(AMD64_YMM13, 381) +CV_REGISTER(AMD64_YMM14, 382) +CV_REGISTER(AMD64_YMM15, 383) + +CV_REGISTER(AMD64_XMM16, 694) +CV_REGISTER(AMD64_XMM17, 695) +CV_REGISTER(AMD64_XMM18, 696) +CV_REGISTER(AMD64_XMM19, 697) +CV_REGISTER(AMD64_XMM20, 698) +CV_REGISTER(AMD64_XMM21, 699) +CV_REGISTER(AMD64_XMM22, 700) +CV_REGISTER(AMD64_XMM23, 701) +CV_REGISTER(AMD64_XMM24, 702) +CV_REGISTER(AMD64_XMM25, 703) +CV_REGISTER(AMD64_XMM26, 704) +CV_REGISTER(AMD64_XMM27, 705) +CV_REGISTER(AMD64_XMM28, 706) +CV_REGISTER(AMD64_XMM29, 707) +CV_REGISTER(AMD64_XMM30, 708) +CV_REGISTER(AMD64_XMM31, 709) + +CV_REGISTER(AMD64_YMM16, 710) +CV_REGISTER(AMD64_YMM17, 711) +CV_REGISTER(AMD64_YMM18, 712) +CV_REGISTER(AMD64_YMM19, 713) +CV_REGISTER(AMD64_YMM20, 714) +CV_REGISTER(AMD64_YMM21, 715) +CV_REGISTER(AMD64_YMM22, 716) +CV_REGISTER(AMD64_YMM23, 717) +CV_REGISTER(AMD64_YMM24, 718) +CV_REGISTER(AMD64_YMM25, 719) +CV_REGISTER(AMD64_YMM26, 720) +CV_REGISTER(AMD64_YMM27, 721) +CV_REGISTER(AMD64_YMM28, 722) +CV_REGISTER(AMD64_YMM29, 723) +CV_REGISTER(AMD64_YMM30, 724) +CV_REGISTER(AMD64_YMM31, 725) + +CV_REGISTER(AMD64_ZMM0, 726) +CV_REGISTER(AMD64_ZMM1, 727) +CV_REGISTER(AMD64_ZMM2, 728) +CV_REGISTER(AMD64_ZMM3, 729) +CV_REGISTER(AMD64_ZMM4, 730) +CV_REGISTER(AMD64_ZMM5, 731) +CV_REGISTER(AMD64_ZMM6, 732) +CV_REGISTER(AMD64_ZMM7, 733) +CV_REGISTER(AMD64_ZMM8, 734) +CV_REGISTER(AMD64_ZMM9, 735) +CV_REGISTER(AMD64_ZMM10, 736) +CV_REGISTER(AMD64_ZMM11, 737) +CV_REGISTER(AMD64_ZMM12, 738) +CV_REGISTER(AMD64_ZMM13, 739) +CV_REGISTER(AMD64_ZMM14, 740) +CV_REGISTER(AMD64_ZMM15, 741) +CV_REGISTER(AMD64_ZMM16, 742) +CV_REGISTER(AMD64_ZMM17, 743) +CV_REGISTER(AMD64_ZMM18, 744) +CV_REGISTER(AMD64_ZMM19, 745) +CV_REGISTER(AMD64_ZMM20, 746) +CV_REGISTER(AMD64_ZMM21, 747) +CV_REGISTER(AMD64_ZMM22, 748) +CV_REGISTER(AMD64_ZMM23, 749) +CV_REGISTER(AMD64_ZMM24, 750) +CV_REGISTER(AMD64_ZMM25, 751) +CV_REGISTER(AMD64_ZMM26, 752) +CV_REGISTER(AMD64_ZMM27, 753) +CV_REGISTER(AMD64_ZMM28, 754) +CV_REGISTER(AMD64_ZMM29, 755) +CV_REGISTER(AMD64_ZMM30, 756) +CV_REGISTER(AMD64_ZMM31, 757) + +CV_REGISTER(AMD64_K0, 758) +CV_REGISTER(AMD64_K1, 759) +CV_REGISTER(AMD64_K2, 760) +CV_REGISTER(AMD64_K3, 761) +CV_REGISTER(AMD64_K4, 762) +CV_REGISTER(AMD64_K5, 763) +CV_REGISTER(AMD64_K6, 764) +CV_REGISTER(AMD64_K7, 765) + +#pragma pop_macro("CR0") +#pragma pop_macro("CR1") +#pragma pop_macro("CR2") +#pragma pop_macro("CR3") +#pragma pop_macro("CR4") diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h index 1e329c7c3f1..847d93f0e98 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" namespace llvm { @@ -26,21 +27,23 @@ public: } Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); FixedStreamArray::Iterator begin() const { return Frames.begin(); } FixedStreamArray::Iterator end() const { return Frames.end(); } - const void *getRelocPtr() const { return RelocPtr; } + const support::ulittle32_t *getRelocPtr() const { return RelocPtr; } private: - const uint32_t *RelocPtr = nullptr; + const support::ulittle32_t *RelocPtr = nullptr; FixedStreamArray Frames; }; class DebugFrameDataSubsection final : public DebugSubsection { public: - DebugFrameDataSubsection() - : DebugSubsection(DebugSubsectionKind::FrameData) {} + DebugFrameDataSubsection(bool IncludeRelocPtr) + : DebugSubsection(DebugSubsectionKind::FrameData), + IncludeRelocPtr(IncludeRelocPtr) {} static bool classof(const DebugSubsection *S) { return S->kind() == DebugSubsectionKind::FrameData; } @@ -52,6 +55,7 @@ public: void setFrames(ArrayRef Frames); private: + bool IncludeRelocPtr = false; std::vector Frames; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h index 58449c2c756..36237e1a4d9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h @@ -180,26 +180,6 @@ template serialize_numeric_impl serialize_numeric(T &Item) { return serialize_numeric_impl(Item); } -// This field is only present in the byte record if the condition is true. The -// condition is evaluated lazily, so it can depend on items that were -// deserialized -// earlier. -#define CV_CONDITIONAL_FIELD(I, C) \ - serialize_conditional(I, [&]() { return !!(C); }) - -// This is an array of N items, where N is evaluated lazily, so it can refer -// to a field deserialized earlier. -#define CV_ARRAY_FIELD_N(I, N) serialize_array(I, [&]() { return N; }) - -// This is an array that exhausts the remainder of the input buffer. -#define CV_ARRAY_FIELD_TAIL(I) serialize_array_tail(I) - -// This is an array that consumes null terminated strings until a double null -// is encountered. -#define CV_STRING_ARRAY_NULL_TERM(I) serialize_null_term_string_array(I) - -#define CV_NUMERIC_FIELD(I) serialize_numeric(I) - template Error consume(BinaryStreamReader &Reader, const serialize_conditional_impl &Item) { @@ -242,9 +222,6 @@ Error consume(BinaryStreamReader &Reader, T &&X, U &&Y, Args &&... Rest) { return consume(Reader, Y, std::forward(Rest)...); } -#define CV_DESERIALIZE(...) \ - if (auto EC = consume(__VA_ARGS__)) \ - return std::move(EC); } } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h index b5479db97a1..6b5dd2d20d1 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -47,7 +47,7 @@ public: return Error::success(); } template static Expected deserializeAs(CVSymbol Symbol) { - T Record(Symbol.kind()); + T Record(static_cast(Symbol.kind())); if (auto EC = deserializeAs(Symbol, Record)) return std::move(EC); return Record; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index 293daa851bd..215da2e2b52 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -27,10 +27,10 @@ class CVSymbolDumper { public: CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types, CodeViewContainer Container, - std::unique_ptr ObjDelegate, + std::unique_ptr ObjDelegate, CPUType CPU, bool PrintRecordBytes) : W(W), Types(Types), Container(Container), - ObjDelegate(std::move(ObjDelegate)), + ObjDelegate(std::move(ObjDelegate)), CompilationCPUType(CPU), PrintRecordBytes(PrintRecordBytes) {} /// Dumps one type record. Returns false if there was a type parsing error, @@ -43,12 +43,14 @@ public: /// parse error, and true otherwise. Error dump(const CVSymbolArray &Symbols); + CPUType getCompilationCPUType() const { return CompilationCPUType; } + private: ScopedPrinter &W; TypeCollection &Types; CodeViewContainer Container; std::unique_ptr ObjDelegate; - + CPUType CompilationCPUType; bool PrintRecordBytes; }; } // end namespace codeview diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 93306824012..b58825c4a78 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -358,6 +358,7 @@ public: // S_PUB32 class PublicSym32 : public SymbolRecord { public: + PublicSym32() : SymbolRecord(SymbolRecordKind::PublicSym32) {} explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {} explicit PublicSym32(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::PublicSym32), @@ -399,6 +400,7 @@ public: uint16_t Module; StringRef Name; + uint16_t modi() const { return Module - 1; } uint32_t RecordOffset; }; @@ -636,6 +638,7 @@ public: // S_OBJNAME class ObjNameSym : public SymbolRecord { public: + explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {} explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} ObjNameSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) { @@ -718,6 +721,7 @@ public: // S_COMPILE3 class Compile3Sym : public SymbolRecord { public: + Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {} explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} Compile3Sym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::Compile3Sym), @@ -739,8 +743,17 @@ public: Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang)); } - uint8_t getLanguage() const { return static_cast(Flags) & 0xFF; } - uint32_t getFlags() const { return static_cast(Flags) & ~0xFF; } + SourceLanguage getLanguage() const { + return static_cast(static_cast(Flags) & 0xFF); + } + CompileSym3Flags getFlags() const { + return static_cast(static_cast(Flags) & ~0xFF); + } + + bool hasOptimizations() const { + return CompileSym3Flags::None != + (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG)); + } uint32_t RecordOffset; }; @@ -761,7 +774,21 @@ public: uint16_t SectionIdOfExceptionHandler; FrameProcedureOptions Flags; + /// Extract the register this frame uses to refer to local variables. + RegisterId getLocalFramePtrReg(CPUType CPU) const { + return decodeFramePtrReg( + EncodedFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U), CPU); + } + + /// Extract the register this frame uses to refer to parameters. + RegisterId getParamFramePtrReg(CPUType CPU) const { + return decodeFramePtrReg( + EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU); + } + uint32_t RecordOffset; + +private: }; // S_CALLSITEINFO diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h new file mode 100644 index 00000000000..3713fe118ea --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h @@ -0,0 +1,62 @@ +//===- SymbolRecordHelpers.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H +#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" + +namespace llvm { +namespace codeview { +/// Return true if this symbol opens a scope. This implies that the symbol has +/// "parent" and "end" fields, which contain the offset of the S_END or +/// S_INLINESITE_END record. +inline bool symbolOpensScope(SymbolKind Kind) { + switch (Kind) { + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + case SymbolKind::S_LPROC32_ID: + case SymbolKind::S_GPROC32_ID: + case SymbolKind::S_BLOCK32: + case SymbolKind::S_SEPCODE: + case SymbolKind::S_THUNK32: + case SymbolKind::S_INLINESITE: + case SymbolKind::S_INLINESITE2: + return true; + default: + break; + } + return false; +} + +/// Return true if this ssymbol ends a scope. +inline bool symbolEndsScope(SymbolKind Kind) { + switch (Kind) { + case SymbolKind::S_END: + case SymbolKind::S_PROC_ID_END: + case SymbolKind::S_INLINESITE_END: + return true; + default: + break; + } + return false; +} + +/// Given a symbol P for which symbolOpensScope(P) == true, return the +/// corresponding end offset. +uint32_t getScopeEndOffset(const CVSymbol &Symbol); +uint32_t getScopeParentOffset(const CVSymbol &Symbol); + +CVSymbolArray limitSymbolArrayToScope(const CVSymbolArray &Symbols, + uint32_t ScopeBegin); + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h index c71281de714..58463a6b13d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -134,6 +134,8 @@ public: return static_cast(Index & SimpleModeMask); } + TypeIndex makeDirect() const { return TypeIndex{getSimpleKind()}; } + static TypeIndex None() { return TypeIndex(SimpleTypeKind::None); } static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); } static TypeIndex VoidPointer32() { @@ -143,6 +145,13 @@ public: return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64); } + static TypeIndex NullptrT() { + // std::nullptr_t uses the pointer mode that doesn't indicate bit-width, + // presumably because std::nullptr_t is intended to be compatible with any + // pointer type. + return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer); + } + static TypeIndex SignedCharacter() { return TypeIndex(SimpleTypeKind::SignedCharacter); } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 61ebdf878ce..7b4a30ee622 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -95,6 +95,11 @@ struct MemberAttributes { return MP == MethodKind::IntroducingVirtual || MP == MethodKind::PureIntroducingVirtual; } + + /// Is this method static. + bool isStatic() const { + return getMethodKind() == MethodKind::Static; + } }; // Does not correspond to any tag, this is the tail of an LF_POINTER record @@ -264,14 +269,18 @@ public: // LF_POINTER class PointerRecord : public TypeRecord { public: + // ---------------------------XXXXX static const uint32_t PointerKindShift = 0; static const uint32_t PointerKindMask = 0x1F; + // ------------------------XXX----- static const uint32_t PointerModeShift = 5; static const uint32_t PointerModeMask = 0x07; - static const uint32_t PointerOptionMask = 0xFF; + // ----------XXX------XXXXX-------- + static const uint32_t PointerOptionMask = 0x381f00; + // -------------XXXXXX------------ static const uint32_t PointerSizeShift = 13; static const uint32_t PointerSizeMask = 0xFF; @@ -305,7 +314,7 @@ public: } PointerOptions getOptions() const { - return static_cast(Attrs); + return static_cast(Attrs & PointerOptionMask); } uint8_t getSize() const { @@ -334,6 +343,14 @@ public: return !!(Attrs & uint32_t(PointerOptions::Restrict)); } + bool isLValueReferenceThisPtr() const { + return !!(Attrs & uint32_t(PointerOptions::LValueRefThisPointer)); + } + + bool isRValueReferenceThisPtr() const { + return !!(Attrs & uint32_t(PointerOptions::RValueRefThisPointer)); + } + TypeIndex ReferentType; uint32_t Attrs; Optional MemberInfo; @@ -429,6 +446,14 @@ public: return (Options & ClassOptions::ForwardReference) != ClassOptions::None; } + bool containsNestedClass() const { + return (Options & ClassOptions::ContainsNestedClass) != ClassOptions::None; + } + + bool isScoped() const { + return (Options & ClassOptions::Scoped) != ClassOptions::None; + } + uint16_t getMemberCount() const { return MemberCount; } ClassOptions getOptions() const { return Options; } TypeIndex getFieldList() const { return FieldList; } @@ -655,7 +680,17 @@ public: ArrayRef getArgs() const { return ArgIndices; } - SmallVector ArgIndices; + /// Indices of known build info arguments. + enum BuildInfoArg { + CurrentDirectory, ///< Absolute CWD path + BuildTool, ///< Absolute compiler path + SourceFile, ///< Path to main source file, relative or absolute + TypeServerPDB, ///< Absolute path of type server PDB (/Fd) + CommandLine, ///< Full canonical command line (maybe -cc1) + MaxArgs + }; + + SmallVector ArgIndices; }; // LF_VFTABLE @@ -923,6 +958,7 @@ public: uint32_t Signature; }; + } // end namespace codeview } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h new file mode 100644 index 00000000000..389472ed1ae --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h @@ -0,0 +1,28 @@ +//===- TypeRecordHelpers.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" + +namespace llvm { + namespace codeview { + /// Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, + /// LF_CLASS, LF_INTERFACE, LF_UNION, or LF_ENUM with the forward ref class + /// option. + bool isUdtForwardRef(CVType CVT); + + /// Given a CVType which is assumed to be an LF_MODIFIER, return the + /// TypeIndex of the type that the LF_MODIFIER modifies. + TypeIndex getModifiedType(const CVType &CVT); + } +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h index 583740d2eb4..0b9f54ec60b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h @@ -83,18 +83,21 @@ Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef Types, Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, SmallVectorImpl &SourceToDest, - const CVTypeArray &IdsAndTypes); + const CVTypeArray &IdsAndTypes, + Optional &PCHSignature); Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes, SmallVectorImpl &SourceToDest, const CVTypeArray &IdsAndTypes, - ArrayRef Hashes); + ArrayRef Hashes, + Optional &PCHSignature); Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, SmallVectorImpl &SourceToDest, const CVTypeArray &Types, - ArrayRef Hashes); + ArrayRef Hashes, + Optional &PCHSignature); Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef Types, SmallVectorImpl &SourceToDest, diff --git a/contrib/llvm/include/llvm/DebugInfo/DIContext.h b/contrib/llvm/include/llvm/DebugInfo/DIContext.h index bbdd5e0d9c3..85e96402a24 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DIContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/DIContext.h @@ -81,7 +81,7 @@ class DIInliningInfo { public: DIInliningInfo() = default; - DILineInfo getFrame(unsigned Index) const { + const DILineInfo & getFrame(unsigned Index) const { assert(Index < Frames.size()); return Frames[Index]; } @@ -98,6 +98,11 @@ public: void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); } + + void resize(unsigned i) { + Frames.resize(i); + } + }; /// Container for description of a global variable. diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h index c219ca75e64..33797419a7b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -18,20 +18,20 @@ namespace llvm { class DWARFCompileUnit : public DWARFUnit { public: DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, - bool IsDWO, const DWARFUnitSectionBase &UnitSection) - : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, - UnitSection) {} + bool IsDWO, const DWARFUnitVector &UnitVector) + : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS, + LS, LE, IsDWO, UnitVector) {} - // VTable anchor. + /// VTable anchor. ~DWARFCompileUnit() override; - - void dump(raw_ostream &OS, DIDumpOptions DumpOpts); - - static const DWARFSectionKind Section = DW_SECT_INFO; + /// Dump this compile unit to \p OS. + void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override; + /// Enable LLVM-style RTTI. + static bool classof(const DWARFUnit *U) { return !U->isTypeUnit(); } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h index f5419fe0242..dbb6be04544 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -57,8 +57,7 @@ enum class ErrorPolicy { Halt, Continue }; /// This data structure is the top level entity that deals with dwarf debug /// information parsing. The actual data is supplied through DWARFObj. class DWARFContext : public DIContext { - DWARFUnitSection CUs; - std::deque> TUs; + DWARFUnitVector NormalUnits; std::unique_ptr CUIndex; std::unique_ptr GdbIndex; std::unique_ptr TUIndex; @@ -75,10 +74,9 @@ class DWARFContext : public DIContext { std::unique_ptr AppleNamespaces; std::unique_ptr AppleObjC; - DWARFUnitSection DWOCUs; - std::deque> DWOTUs; + DWARFUnitVector DWOUnits; std::unique_ptr AbbrevDWO; - std::unique_ptr LocDWO; + std::unique_ptr LocDWO; /// The maximum DWARF version of all units. unsigned MaxVersion = 0; @@ -95,22 +93,17 @@ class DWARFContext : public DIContext { std::unique_ptr RegInfo; /// Read compile units from the debug_info section (if necessary) - /// and store them in CUs. - void parseCompileUnits(); - - /// Read type units from the debug_types sections (if necessary) - /// and store them in TUs. - void parseTypeUnits(); + /// and type units from the debug_types sections (if necessary) + /// and store them in NormalUnits. + void parseNormalUnits(); /// Read compile units from the debug_info.dwo section (if necessary) - /// and store them in DWOCUs. - void parseDWOCompileUnits(); + /// and type units from the debug_types.dwo section (if necessary) + /// and store them in DWOUnits. + /// If \p Lazy is true, set up to parse but don't actually parse them. + enum { EagerParse = false, LazyParse = true }; + void parseDWOUnits(bool Lazy = false); - /// Read type units from the debug_types.dwo section (if necessary) - /// and store them in DWOTUs. - void parseDWOTypeUnits(); - -protected: std::unique_ptr DObj; public: @@ -139,68 +132,95 @@ public: bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; - using cu_iterator_range = DWARFUnitSection::iterator_range; - using tu_iterator_range = DWARFUnitSection::iterator_range; - using tu_section_iterator_range = iterator_range; + using unit_iterator_range = DWARFUnitVector::iterator_range; - /// Get compile units in this context. - cu_iterator_range compile_units() { - parseCompileUnits(); - return cu_iterator_range(CUs.begin(), CUs.end()); + /// Get units from .debug_info in this context. + unit_iterator_range info_section_units() { + parseNormalUnits(); + return unit_iterator_range(NormalUnits.begin(), + NormalUnits.begin() + + NormalUnits.getNumInfoUnits()); } + /// Get units from .debug_types in this context. + unit_iterator_range types_section_units() { + parseNormalUnits(); + return unit_iterator_range( + NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end()); + } + + /// Get compile units in this context. + unit_iterator_range compile_units() { return info_section_units(); } + /// Get type units in this context. - tu_section_iterator_range type_unit_sections() { - parseTypeUnits(); - return tu_section_iterator_range(TUs.begin(), TUs.end()); + unit_iterator_range type_units() { return types_section_units(); } + + /// Get all normal compile/type units in this context. + unit_iterator_range normal_units() { + parseNormalUnits(); + return unit_iterator_range(NormalUnits.begin(), NormalUnits.end()); + } + + /// Get units from .debug_info..dwo in the DWO context. + unit_iterator_range dwo_info_section_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin(), + DWOUnits.begin() + DWOUnits.getNumInfoUnits()); + } + + /// Get units from .debug_types.dwo in the DWO context. + unit_iterator_range dwo_types_section_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(), + DWOUnits.end()); } /// Get compile units in the DWO context. - cu_iterator_range dwo_compile_units() { - parseDWOCompileUnits(); - return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); - } + unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); } /// Get type units in the DWO context. - tu_section_iterator_range dwo_type_unit_sections() { - parseDWOTypeUnits(); - return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); + unit_iterator_range dwo_type_units() { return dwo_types_section_units(); } + + /// Get all units in the DWO context. + unit_iterator_range dwo_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin(), DWOUnits.end()); } /// Get the number of compile units in this context. unsigned getNumCompileUnits() { - parseCompileUnits(); - return CUs.size(); + parseNormalUnits(); + return NormalUnits.getNumInfoUnits(); } - /// Get the number of compile units in this context. + /// Get the number of type units in this context. unsigned getNumTypeUnits() { - parseTypeUnits(); - return TUs.size(); + parseNormalUnits(); + return NormalUnits.getNumTypesUnits(); } /// Get the number of compile units in the DWO context. unsigned getNumDWOCompileUnits() { - parseDWOCompileUnits(); - return DWOCUs.size(); + parseDWOUnits(); + return DWOUnits.getNumInfoUnits(); } - /// Get the number of compile units in the DWO context. + /// Get the number of type units in the DWO context. unsigned getNumDWOTypeUnits() { - parseDWOTypeUnits(); - return DWOTUs.size(); + parseDWOUnits(); + return DWOUnits.getNumTypesUnits(); } - /// Get the compile unit at the specified index for this compile unit. - DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { - parseCompileUnits(); - return CUs[index].get(); + /// Get the unit at the specified index. + DWARFUnit *getUnitAtIndex(unsigned index) { + parseNormalUnits(); + return NormalUnits[index].get(); } - /// Get the compile unit at the specified index for the DWO compile units. - DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { - parseDWOCompileUnits(); - return DWOCUs[index].get(); + /// Get the unit at the specified index for the DWO units. + DWARFUnit *getDWOUnitAtIndex(unsigned index) { + parseDWOUnits(); + return DWOUnits[index].get(); } DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); @@ -211,7 +231,17 @@ public: /// Get a DIE given an exact offset. DWARFDie getDIEForOffset(uint32_t Offset); - unsigned getMaxVersion() const { return MaxVersion; } + unsigned getMaxVersion() { + // Ensure info units have been parsed to discover MaxVersion + info_section_units(); + return MaxVersion; + } + + unsigned getMaxDWOVersion() { + // Ensure DWO info units have been parsed to discover MaxVersion + dwo_info_section_units(); + return MaxVersion; + } void setMaxVersionIfGreater(unsigned Version) { if (Version > MaxVersion) @@ -232,7 +262,7 @@ public: const DWARFDebugAbbrev *getDebugAbbrevDWO(); /// Get a pointer to the parsed DebugLoc object. - const DWARFDebugLocDWO *getDebugLocDWO(); + const DWARFDebugLoclists *getDebugLocDWO(); /// Get a pointer to the parsed DebugAranges object. const DWARFDebugAranges *getDebugAranges(); @@ -327,6 +357,13 @@ public: /// TODO: refactor compile_units() to make this const. uint8_t getCUAddrSize(); + /// Dump Error as warning message to stderr. + static void dumpWarning(Error Warning); + + Triple::ArchType getArch() const { + return getDWARFObj().getFile()->getArch(); + } + private: /// Return the compile unit which contains instruction with provided /// address. diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index ff1c7fb3838..7dc07d774ab 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -13,6 +13,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Triple.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/Support/Error.h" @@ -59,9 +60,11 @@ public: unsigned size() const { return (unsigned)Instructions.size(); } bool empty() const { return Instructions.empty(); } - CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor) + CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, + Triple::ArchType Arch) : CodeAlignmentFactor(CodeAlignmentFactor), - DataAlignmentFactor(DataAlignmentFactor) {} + DataAlignmentFactor(DataAlignmentFactor), + Arch(Arch) {} /// Parse and store a sequence of CFI instructions from Data, /// starting at *Offset and ending at EndOffset. *Offset is updated @@ -76,6 +79,7 @@ private: std::vector Instructions; const uint64_t CodeAlignmentFactor; const int64_t DataAlignmentFactor; + Triple::ArchType Arch; /// Convenience method to add a new instruction with the given opcode. void addInstruction(uint8_t Opcode) { @@ -130,8 +134,9 @@ public: enum FrameKind { FK_CIE, FK_FDE }; FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, - int64_t DataAlign) - : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {} + int64_t DataAlign, Triple::ArchType Arch) + : Kind(K), Offset(Offset), Length(Length), + CFIs(CodeAlign, DataAlign, Arch) {} virtual ~FrameEntry() {} @@ -168,9 +173,9 @@ public: int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, uint32_t LSDAPointerEncoding, Optional Personality, - Optional PersonalityEnc) + Optional PersonalityEnc, Triple::ArchType Arch) : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor, - DataAlignmentFactor), + DataAlignmentFactor, Arch), Version(Version), Augmentation(std::move(Augmentation)), AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), CodeAlignmentFactor(CodeAlignmentFactor), @@ -224,10 +229,11 @@ public: // is obtained lazily once it's actually required. FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, - Optional LSDAAddress) + Optional LSDAAddress, Triple::ArchType Arch) : FrameEntry(FK_FDE, Offset, Length, Cie ? Cie->getCodeAlignmentFactor() : 0, - Cie ? Cie->getDataAlignmentFactor() : 0), + Cie ? Cie->getDataAlignmentFactor() : 0, + Arch), LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation), AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} @@ -256,6 +262,7 @@ private: /// A parsed .debug_frame or .eh_frame section class DWARFDebugFrame { + const Triple::ArchType Arch; // True if this is parsing an eh_frame section. const bool IsEH; // Not zero for sane pointer values coming out of eh_frame @@ -272,7 +279,8 @@ public: // it is a .debug_frame section. EHFrameAddress should be different // than zero for correct parsing of .eh_frame addresses when they // use a PC-relative encoding. - DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0); + DWARFDebugFrame(Triple::ArchType Arch, + bool IsEH = false, uint64_t EHFrameAddress = 0); ~DWARFDebugFrame(); /// Dump the section data into the given stream. diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index 5b2af34bbcf..d50af5a057f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -247,10 +247,11 @@ public: void clear(); /// Parse prologue and all rows. - Error parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, - const DWARFContext &Ctx, const DWARFUnit *U, - std::function RecoverableErrorCallback = warn, - raw_ostream *OS = nullptr); + Error parse( + DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + const DWARFContext &Ctx, const DWARFUnit *U, + std::function RecoverableErrorCallback, + raw_ostream *OS = nullptr); using RowVector = std::vector; using RowIter = RowVector::const_iterator; @@ -273,14 +274,13 @@ public: Expected getOrParseLineTable( DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, - std::function RecoverableErrorCallback = warn); + std::function RecoverableErrorCallback); /// Helper to allow for parsing of an entire .debug_line section in sequence. class SectionParser { public: - using cu_range = DWARFUnitSection::iterator_range; - using tu_range = - iterator_range>::iterator>; + using cu_range = DWARFUnitVector::iterator_range; + using tu_range = DWARFUnitVector::iterator_range; using LineToUnitMap = std::map; SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs, @@ -296,16 +296,17 @@ public: /// \param OS - if not null, the parser will print information about the /// table as it parses it. LineTable - parseNext(function_ref RecoverableErrorCallback = warn, - function_ref UnrecoverableErrorCallback = warn, - raw_ostream *OS = nullptr); + parseNext( + function_ref RecoverableErrorCallback, + function_ref UnrecoverableErrorCallback, + raw_ostream *OS = nullptr); /// Skip the current line table and go to the following line table (if /// present) immediately. /// /// \param ErrorCallback - report any prologue parsing issues via this /// callback. - void skip(function_ref ErrorCallback = warn); + void skip(function_ref ErrorCallback); /// Indicates if the parser has parsed as much as possible. /// @@ -328,12 +329,6 @@ public: bool Done = false; }; - /// Helper function for DWARFDebugLine parse functions, to report issues - /// identified during parsing. - /// - /// \param Err The Error to report. - static void warn(Error Err); - private: struct ParsingState { ParsingState(struct LineTable *LT); diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index 9a73745fb6b..da2098e1540 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -73,19 +73,21 @@ public: uint32_t *Offset); }; -class DWARFDebugLocDWO { +class DWARFDebugLoclists { public: struct Entry { - uint64_t Start; - uint32_t Length; + uint8_t Kind; + uint64_t Value0; + uint64_t Value1; SmallVector Loc; }; struct LocationList { unsigned Offset; SmallVector Entries; - void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *RegInfo, unsigned Indent) const; + void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, + unsigned AddressSize, const MCRegisterInfo *RegInfo, + unsigned Indent) const; }; private: @@ -98,15 +100,15 @@ private: bool IsLittleEndian; public: - void parse(DataExtractor data); - void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, + void parse(DataExtractor data, unsigned Version); + void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo, Optional Offset) const; /// Return the location list at the given offset or nullptr. LocationList const *getLocationListAtOffset(uint64_t Offset) const; - static Optional parseOneLocationList(DataExtractor Data, - uint32_t *Offset); + static Optional + parseOneLocationList(DataExtractor Data, unsigned *Offset, unsigned Version); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h index cae4804e61d..9e1656eb161 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h @@ -13,6 +13,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" #include #include @@ -67,7 +68,8 @@ private: bool GnuStyle; public: - DWARFDebugPubTable(StringRef Data, bool LittleEndian, bool GnuStyle); + DWARFDebugPubTable(const DWARFObject &Obj, const DWARFSection &Sec, + bool LittleEndian, bool GnuStyle); void dump(raw_ostream &OS) const; diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h index ce7436d9faa..bc26edf0064 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -18,7 +18,6 @@ namespace llvm { -struct BaseAddress; class raw_ostream; class DWARFDebugRangeList { @@ -78,7 +77,7 @@ public: /// list. Has to be passed base address of the compile unit referencing this /// range list. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional BaseAddr) const; + getAbsoluteRanges(llvm::Optional BaseAddr) const; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h index e2e8ab5ed21..5cc8d789e59 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H #define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H +#include "llvm/ADT/Optional.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" @@ -23,6 +24,7 @@ namespace llvm { class Error; class raw_ostream; +class DWARFUnit; /// A class representing a single range list entry. struct RangeListEntry : public DWARFListEntryBase { @@ -35,7 +37,9 @@ struct RangeListEntry : public DWARFListEntryBase { Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, - uint64_t &CurrentBase, DIDumpOptions DumpOpts) const; + uint64_t &CurrentBase, DIDumpOptions DumpOpts, + llvm::function_ref(uint32_t)> + LookupPooledAddress) const; bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } }; @@ -44,7 +48,8 @@ class DWARFDebugRnglist : public DWARFListType { public: /// Build a DWARFAddressRangesVector from a rangelist. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional BaseAddr) const; + getAbsoluteRanges(llvm::Optional BaseAddr, + DWARFUnit &U) const; }; class DWARFDebugRnglistTable : public DWARFListTableBase { diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h index c77034f6348..56d46cd739a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -180,6 +180,7 @@ public: /// \returns a valid DWARFDie instance if the attribute exists, or an invalid /// DWARFDie object if it doesn't. DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const; + DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const; /// Extract the range base attribute from this DIE as absolute section offset. /// @@ -404,6 +405,10 @@ public: Die = Die.getPreviousSibling(); } + llvm::DWARFDie::iterator base() const { + return llvm::DWARFDie::iterator(AtEnd ? Die : Die.getSibling()); + } + reverse_iterator &operator++() { assert(!AtEnd && "Incrementing rend"); llvm::DWARFDie D = Die.getPreviousSibling(); diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 1b5f71c946f..727e853c09f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -61,7 +61,6 @@ public: dwarf::Form getForm() const { return Form; } uint64_t getRawUValue() const { return Value.uval; } - uint64_t getSectionIndex() const { return Value.SectionIndex; } void setForm(dwarf::Form F) { Form = F; } void setUValue(uint64_t V) { Value.uval = V; } void setSValue(int64_t V) { Value.sval = V; } @@ -75,6 +74,10 @@ public: bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; + void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, + SectionedAddress SA) const; + static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, + DIDumpOptions DumpOpts, uint64_t SectionIndex); /// Extracts a value in \p Data at offset \p *OffsetPtr. The information /// in \p FormParams is needed to interpret some forms. The optional @@ -101,6 +104,7 @@ public: Optional getAsSignedConstant() const; Optional getAsCString() const; Optional getAsAddress() const; + Optional getAsSectionedAddress() const; Optional getAsSectionOffset() const; Optional> getAsBlock() const; Optional getAsCStringOffset() const; @@ -238,6 +242,13 @@ inline Optional toAddress(const Optional &V) { return None; } +inline Optional +toSectionedAddress(const Optional &V) { + if (V) + return V->getAsSectionedAddress(); + return None; +} + /// Take an optional DWARFFormValue and extract a address. /// /// \param V and optional DWARFFormValue to attempt to extract the value from. diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h index 8d1ac5c83c2..073e02903c3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h @@ -24,6 +24,7 @@ class DWARFGdbIndex { uint32_t Version; uint32_t CuListOffset; + uint32_t TuListOffset; uint32_t AddressAreaOffset; uint32_t SymbolTableOffset; uint32_t ConstantPoolOffset; @@ -34,6 +35,13 @@ class DWARFGdbIndex { }; SmallVector CuList; + struct TypeUnitEntry { + uint64_t Offset; + uint64_t TypeOffset; + uint64_t TypeSignature; + }; + SmallVector TuList; + struct AddressEntry { uint64_t LowAddress; /// The low address. uint64_t HighAddress; /// The high address. @@ -55,6 +63,7 @@ class DWARFGdbIndex { uint32_t StringPoolOffset; void dumpCUList(raw_ostream &OS) const; + void dumpTUList(raw_ostream &OS) const; void dumpAddressArea(raw_ostream &OS) const; void dumpSymbolTable(raw_ostream &OS) const; void dumpConstantPool(raw_ostream &OS) const; diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h index ab12f3bc08b..9b987314f20 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -13,6 +13,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -43,10 +44,6 @@ protected: ListEntries Entries; public: - // FIXME: We need to consolidate the various verions of "createError" - // that are used in the DWARF consumer. Until then, this is a workaround. - Error createError(const char *, const char *, uint32_t); - const ListEntries &getEntries() const { return Entries; } bool empty() const { return Entries.empty(); } void clear() { Entries.clear(); } @@ -102,6 +99,7 @@ public: uint32_t getHeaderOffset() const { return HeaderOffset; } uint8_t getAddrSize() const { return HeaderData.AddrSize; } uint32_t getLength() const { return HeaderData.Length; } + uint16_t getVersion() const { return HeaderData.Version; } StringRef getSectionName() const { return SectionName; } StringRef getListTypeString() const { return ListTypeString; } dwarf::DwarfFormat getFormat() const { return Format; } @@ -159,7 +157,10 @@ public: uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); } uint8_t getAddrSize() const { return Header.getAddrSize(); } - void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; + void dump(raw_ostream &OS, + llvm::function_ref(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts = {}) const; /// Return the contents of the offset entry designated by a given index. Optional getOffsetEntry(uint32_t Index) const { @@ -213,7 +214,8 @@ Error DWARFListType::extract(DWARFDataExtractor Data, StringRef SectionName, StringRef ListTypeString) { if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) - return createError("invalid %s list offset 0x%" PRIx32, + return createStringError(errc::invalid_argument, + "invalid %s list offset 0x%" PRIx32, ListTypeString.data(), *OffsetPtr); Entries.clear(); while (*OffsetPtr < End) { @@ -224,14 +226,18 @@ Error DWARFListType::extract(DWARFDataExtractor Data, if (Entry.isSentinel()) return Error::success(); } - return createError("no end of list marker detected at end of %s table " + return createStringError(errc::illegal_byte_sequence, + "no end of list marker detected at end of %s table " "starting at offset 0x%" PRIx32, SectionName.data(), HeaderOffset); } template -void DWARFListTableBase::dump(raw_ostream &OS, - DIDumpOptions DumpOpts) const { +void DWARFListTableBase::dump( + raw_ostream &OS, + llvm::function_ref(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) const { Header.dump(OS, DumpOpts); OS << HeaderString << "\n"; @@ -250,7 +256,7 @@ void DWARFListTableBase::dump(raw_ostream &OS, for (const auto &List : ListMap) for (const auto &Entry : List.second.getEntries()) Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase, - DumpOpts); + DumpOpts, LookupPooledAddress); } template diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h index 6e8f370f4ae..d611b5d075c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -33,11 +33,13 @@ public: virtual ArrayRef getSectionNames() const { return {}; } virtual bool isLittleEndian() const = 0; virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); } - virtual const DWARFSection &getInfoSection() const { return Dummy; } + virtual void + forEachInfoSections(function_ref F) const {} virtual void forEachTypesSections(function_ref F) const {} virtual StringRef getAbbrevSection() const { return ""; } virtual const DWARFSection &getLocSection() const { return Dummy; } + virtual const DWARFSection &getLoclistsSection() const { return Dummy; } virtual StringRef getARangeSection() const { return ""; } virtual StringRef getDebugFrameSection() const { return ""; } virtual StringRef getEHFrameSection() const { return ""; } @@ -47,12 +49,13 @@ public: virtual const DWARFSection &getRangeSection() const { return Dummy; } virtual const DWARFSection &getRnglistsSection() const { return Dummy; } virtual StringRef getMacinfoSection() const { return ""; } - virtual StringRef getPubNamesSection() const { return ""; } - virtual StringRef getPubTypesSection() const { return ""; } - virtual StringRef getGnuPubNamesSection() const { return ""; } - virtual StringRef getGnuPubTypesSection() const { return ""; } + virtual const DWARFSection &getPubNamesSection() const { return Dummy; } + virtual const DWARFSection &getPubTypesSection() const { return Dummy; } + virtual const DWARFSection &getGnuPubNamesSection() const { return Dummy; } + virtual const DWARFSection &getGnuPubTypesSection() const { return Dummy; } virtual const DWARFSection &getStringOffsetSection() const { return Dummy; } - virtual const DWARFSection &getInfoDWOSection() const { return Dummy; } + virtual void + forEachInfoDWOSections(function_ref F) const {} virtual void forEachTypesDWOSections(function_ref F) const {} virtual StringRef getAbbrevDWOSection() const { return ""; } diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFSection.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFSection.h index 77045f0794a..7f823596529 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFSection.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -23,6 +23,11 @@ struct SectionName { bool IsNameUnique; }; +struct SectionedAddress { + uint64_t Address; + uint64_t SectionIndex; +}; + } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index cb5a78ee3db..8ca5ba13fc2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -26,19 +26,20 @@ class raw_ostream; class DWARFTypeUnit : public DWARFUnit { public: DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, - const DWARFUnitSectionBase &UnitSection) - : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, - UnitSection) {} + const DWARFUnitVector &UnitVector) + : DWARFUnit(Context, Section, Header, DA, RS, LocSection, SS, SOS, AOS, + LS, LE, IsDWO, UnitVector) {} uint64_t getTypeHash() const { return getHeader().getTypeHash(); } uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); } - void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}); - static const DWARFSectionKind Section = DW_SECT_TYPES; + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; + // Enable LLVM-style RTTI. + static bool classof(const DWARFUnit *U) { return U->isTypeUnit(); } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 988a7958184..79c3ce1106d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -72,7 +72,8 @@ public: /// Parse a unit header from \p debug_info starting at \p offset_ptr. bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, uint32_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO, - const DWARFUnitIndex *Index = nullptr); + const DWARFUnitIndex *Index = nullptr, + const DWARFUnitIndex::Entry *Entry = nullptr); uint32_t getOffset() const { return Offset; } const dwarf::FormParams &getFormParams() const { return FormParams; } uint16_t getVersion() const { return FormParams.Version; } @@ -101,133 +102,66 @@ public: uint32_t getNextUnitOffset() const { return Offset + Length + 4; } }; -/// Base class for all DWARFUnitSection classes. This provides the -/// functionality common to all unit types. -class DWARFUnitSectionBase { -public: - /// Returns the Unit that contains the given section offset in the - /// same section this Unit originated from. - virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; - virtual DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) = 0; - - void parse(DWARFContext &C, const DWARFSection &Section); - void parseDWO(DWARFContext &C, const DWARFSection &DWOSection, - bool Lazy = false); - -protected: - ~DWARFUnitSectionBase() = default; - - virtual void parseImpl(DWARFContext &Context, const DWARFObject &Obj, - const DWARFSection &Section, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, - StringRef SS, const DWARFSection &SOS, - const DWARFSection *AOS, const DWARFSection &LS, - bool isLittleEndian, bool isDWO, bool Lazy) = 0; -}; - const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, DWARFSectionKind Kind); -/// Concrete instance of DWARFUnitSection, specialized for one Unit type. -template -class DWARFUnitSection final : public SmallVector, 1>, - public DWARFUnitSectionBase { - bool Parsed = false; - std::function(uint32_t)> Parser; +/// Describe a collection of units. Intended to hold all units either from +/// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo. +class DWARFUnitVector final : public SmallVector, 1> { + std::function(uint32_t, DWARFSectionKind, + const DWARFSection *, + const DWARFUnitIndex::Entry *)> + Parser; + int NumInfoUnits = -1; public: - using UnitVector = SmallVectorImpl>; + using UnitVector = SmallVectorImpl>; using iterator = typename UnitVector::iterator; using iterator_range = llvm::iterator_range; - UnitType *getUnitForOffset(uint32_t Offset) const override { - auto *CU = std::upper_bound( - this->begin(), this->end(), Offset, - [](uint32_t LHS, const std::unique_ptr &RHS) { - return LHS < RHS->getNextUnitOffset(); - }); - if (CU != this->end() && (*CU)->getOffset() <= Offset) - return CU->get(); - return nullptr; - } - UnitType *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) override { - const auto *CUOff = E.getOffset(DW_SECT_INFO); - if (!CUOff) - return nullptr; - - auto Offset = CUOff->Offset; - - auto *CU = std::upper_bound( - this->begin(), this->end(), CUOff->Offset, - [](uint32_t LHS, const std::unique_ptr &RHS) { - return LHS < RHS->getNextUnitOffset(); - }); - if (CU != this->end() && (*CU)->getOffset() <= Offset) - return CU->get(); - - if (!Parser) - return nullptr; - - auto U = Parser(Offset); - if (!U) - U = nullptr; - - auto *NewCU = U.get(); - this->insert(CU, std::move(U)); - return NewCU; + DWARFUnit *getUnitForOffset(uint32_t Offset) const; + DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E); + + /// Read units from a .debug_info or .debug_types section. Calls made + /// before finishedInfoUnits() are assumed to be for .debug_info sections, + /// calls after finishedInfoUnits() are for .debug_types sections. Caller + /// must not mix calls to addUnitsForSection and addUnitsForDWOSection. + void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, + DWARFSectionKind SectionKind); + /// Read units from a .debug_info.dwo or .debug_types.dwo section. Calls + /// made before finishedInfoUnits() are assumed to be for .debug_info.dwo + /// sections, calls after finishedInfoUnits() are for .debug_types.dwo + /// sections. Caller must not mix calls to addUnitsForSection and + /// addUnitsForDWOSection. + void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection, + DWARFSectionKind SectionKind, bool Lazy = false); + + /// Add an existing DWARFUnit to this UnitVector. This is used by the DWARF + /// verifier to process unit separately. + DWARFUnit *addUnit(std::unique_ptr Unit); + + /// Returns number of all units held by this instance. + unsigned getNumUnits() const { return size(); } + /// Returns number of units from all .debug_info[.dwo] sections. + unsigned getNumInfoUnits() const { + return NumInfoUnits == -1 ? size() : NumInfoUnits; } + /// Returns number of units from all .debug_types[.dwo] sections. + unsigned getNumTypesUnits() const { return size() - NumInfoUnits; } + /// Indicate that parsing .debug_info[.dwo] is done, and remaining units + /// will be from .debug_types[.dwo]. + void finishedInfoUnits() { NumInfoUnits = size(); } private: - void parseImpl(DWARFContext &Context, const DWARFObject &Obj, - const DWARFSection &Section, const DWARFDebugAbbrev *DA, - const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, - const DWARFSection *AOS, const DWARFSection &LS, bool LE, - bool IsDWO, bool Lazy) override { - if (Parsed) - return; - DWARFDataExtractor Data(Obj, Section, LE, 0); - if (!Parser) { - const DWARFUnitIndex *Index = nullptr; - if (IsDWO) - Index = &getDWARFUnitIndex(Context, UnitType::Section); - Parser = [=, &Context, &Section, &SOS, - &LS](uint32_t Offset) -> std::unique_ptr { - if (!Data.isValidOffset(Offset)) - return nullptr; - DWARFUnitHeader Header; - if (!Header.extract(Context, Data, &Offset, UnitType::Section, Index)) - return nullptr; - auto U = llvm::make_unique( - Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, - *this); - return U; - }; - } - if (Lazy) - return; - auto I = this->begin(); - uint32_t Offset = 0; - while (Data.isValidOffset(Offset)) { - if (I != this->end() && (*I)->getOffset() == Offset) { - ++I; - continue; - } - auto U = Parser(Offset); - if (!U) - break; - Offset = U->getNextUnitOffset(); - I = std::next(this->insert(I, std::move(U))); - } - Parsed = true; - } + void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj, + const DWARFSection &Section, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, + const DWARFSection *AOS, const DWARFSection &LS, bool LE, + bool IsDWO, bool Lazy, DWARFSectionKind SectionKind); }; /// Represents base address of the CU. -struct BaseAddress { - uint64_t Address; - uint64_t SectionIndex; -}; - /// Represents a unit's contribution to the string offsets table. struct StrOffsetsContributionDescriptor { uint64_t Base = 0; @@ -261,14 +195,20 @@ class DWARFUnit { const DWARFDebugAbbrev *Abbrev; const DWARFSection *RangeSection; uint32_t RangeSectionBase; + /// We either keep track of the location list section or its data, depending + /// on whether we are handling a split DWARF section or not. + union { + const DWARFSection *LocSection; + StringRef LocSectionData; + }; const DWARFSection &LineSection; StringRef StringSection; const DWARFSection &StringOffsetSection; const DWARFSection *AddrOffsetSection; uint32_t AddrOffsetSectionBase = 0; bool isLittleEndian; - bool isDWO; - const DWARFUnitSectionBase &UnitSection; + bool IsDWO; + const DWARFUnitVector &UnitVector; /// Start, length, and DWARF format of the unit's contribution to the string /// offsets table (DWARF v5). @@ -278,7 +218,7 @@ class DWARFUnit { Optional RngListTable; mutable const DWARFAbbreviationDeclarationSet *Abbrevs; - llvm::Optional BaseAddr; + llvm::Optional BaseAddr; /// The compile unit debug information entry items. std::vector DieArray; @@ -308,28 +248,30 @@ protected: /// length and form. The given offset is expected to be derived from the unit /// DIE's DW_AT_str_offsets_base attribute. Optional - determineStringOffsetsTableContribution(DWARFDataExtractor &DA, - uint64_t Offset); + determineStringOffsetsTableContribution(DWARFDataExtractor &DA); /// Find the unit's contribution to the string offsets table and determine its /// length and form. The given offset is expected to be 0 in a dwo file or, /// in a dwp file, the start of the unit's contribution to the string offsets /// table section (as determined by the index table). Optional - determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA, - uint64_t Offset); + determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA); public: DWARFUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, - const DWARFSection &SOS, const DWARFSection *AOS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, + StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, - const DWARFUnitSectionBase &UnitSection); + const DWARFUnitVector &UnitVector); virtual ~DWARFUnit(); + bool isDWOUnit() const { return IsDWO; } DWARFContext& getContext() const { return Context; } + const DWARFSection &getInfoSection() const { return InfoSection; } + const DWARFSection *getLocSection() const { return LocSection; } + StringRef getLocSectionData() const { return LocSectionData; } uint32_t getOffset() const { return Header.getOffset(); } const dwarf::FormParams &getFormParams() const { return Header.getFormParams(); @@ -342,6 +284,7 @@ public: } uint32_t getLength() const { return Header.getLength(); } uint8_t getUnitType() const { return Header.getUnitType(); } + bool isTypeUnit() const { return Header.isTypeUnit(); } uint32_t getNextUnitOffset() const { return Header.getNextUnitOffset(); } const DWARFSection &getLineSection() const { return LineSection; } StringRef getStringSection() const { return StringSection; } @@ -362,8 +305,8 @@ public: RangeSectionBase = Base; } - bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; - bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const; + Optional getAddrOffsetSectionItem(uint32_t Index) const; + Optional getStringOffsetSectionItem(uint32_t Index) const; DWARFDataExtractor getDebugInfoExtractor() const; @@ -433,7 +376,7 @@ public: llvm_unreachable("Invalid UnitType."); } - llvm::Optional getBaseAddress(); + llvm::Optional getBaseAddress(); DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { extractDIEsIfNeeded(ExtractUnitDIEOnly); @@ -467,7 +410,7 @@ public: return None; } - void collectAddressRanges(DWARFAddressRangesVector &CURanges); + Expected collectAddressRanges(); /// Returns subprogram DIE with address range encompassing the provided /// address. The pointer is alive as long as parsed compile unit DIEs are not @@ -480,8 +423,8 @@ public: void getInlinedChainForAddress(uint64_t Address, SmallVectorImpl &InlinedChain); - /// getUnitSection - Return the DWARFUnitSection containing this unit. - const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } + /// Return the DWARFUnitVector containing this unit. + const DWARFUnitVector &getUnitVector() const { return UnitVector; } /// Returns the number of DIEs in the unit. Parses the unit /// if necessary. @@ -541,6 +484,7 @@ public: return die_iterator_range(DieArray.begin(), DieArray.end()); } + virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0; private: /// Size in bytes of the .debug_info data associated with this compile unit. size_t getDebugInfoSize() const { diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h index 49ed4bb222f..16be5f9401c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h @@ -74,6 +74,7 @@ private: int InfoColumn = -1; std::unique_ptr ColumnKinds; std::unique_ptr Rows; + mutable std::vector OffsetLookup; static StringRef getColumnHeader(DWARFSectionKind DS); diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index a829510a219..e47fbea5646 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include #include @@ -96,10 +97,14 @@ private: /// lies between to valid DIEs. std::map> ReferenceToDIEOffsets; uint32_t NumDebugLineErrors = 0; + // Used to relax some checks that do not currently work portably + bool IsObjectFile; + bool IsMachOObject; raw_ostream &error() const; raw_ostream &warn() const; raw_ostream ¬e() const; + raw_ostream &dump(const DWARFDie &Die, unsigned indent = 0) const; /// Verifies the abbreviations section. /// @@ -113,20 +118,20 @@ private: /// \returns The number of errors that occurred during verification. unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev); - /// Verifies the header of a unit in the .debug_info section. + /// Verifies the header of a unit in a .debug_info or .debug_types section. /// /// This function currently checks for: /// - Unit is in 32-bit DWARF format. The function can be modified to /// support 64-bit format. /// - The DWARF version is valid /// - The unit type is valid (if unit is in version >=5) - /// - The unit doesn't extend beyond .debug_info section + /// - The unit doesn't extend beyond the containing section /// - The address size is valid /// - The offset in the .debug_abbrev section is valid /// - /// \param DebugInfoData The .debug_info section data + /// \param DebugInfoData The section data /// \param Offset A reference to the offset start of the unit. The offset will - /// be updated to point to the next unit in .debug_info + /// be updated to point to the next unit in the section /// \param UnitIndex The index of the unit to be verified /// \param UnitType A reference to the type of the unit /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is @@ -137,7 +142,7 @@ private: uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType, bool &isUnitDWARF64); - /// Verifies the header of a unit in the .debug_info section. + /// Verifies the header of a unit in a .debug_info or .debug_types section. /// /// This function currently verifies: /// - The debug info attributes. @@ -146,13 +151,29 @@ private: /// - That the root DIE is a unit DIE. /// - If a unit type is provided, that the unit DIE matches the unit type. /// - The DIE ranges. + /// - That call site entries are only nested within subprograms with a + /// DW_AT_call attribute. /// - /// \param Unit The DWARF Unit to verifiy. - /// \param UnitType An optional unit type which will be used to verify the - /// type of the unit DIE. + /// \param Unit The DWARF Unit to verify. /// - /// \returns true if the content is verified successfully, false otherwise. - bool verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType = 0); + /// \returns The number of errors that occurred during verification. + unsigned verifyUnitContents(DWARFUnit &Unit); + + /// Verifies the unit headers and contents in a .debug_info or .debug_types + /// section. + /// + /// \param S The DWARF Section to verify. + /// \param SectionKind The object-file section kind that S comes from. + /// + /// \returns The number of errors that occurred during verification. + unsigned verifyUnitSection(const DWARFSection &S, + DWARFSectionKind SectionKind); + + /// Verifies that a call site entry is nested within a subprogram with a + /// DW_AT_call attribute. + /// + /// \returns Number of errors that occurred during verification. + unsigned verifyDebugInfoCallSite(const DWARFDie &Die); /// Verify that all Die ranges are valid. /// @@ -172,7 +193,7 @@ private: /// \param AttrValue The DWARF attribute value to check /// /// \returns NumErrors The number of errors occurred during verification of - /// attributes' values in a .debug_info section unit + /// attributes' values in a unit unsigned verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue); @@ -180,14 +201,14 @@ private: /// /// This function currently checks for: /// - All DW_FORM_ref values that are CU relative have valid CU offsets - /// - All DW_FORM_ref_addr values have valid .debug_info offsets + /// - All DW_FORM_ref_addr values have valid section offsets /// - All DW_FORM_strp values have valid .debug_str offsets /// /// \param Die The DWARF DIE that owns the attribute value /// \param AttrValue The DWARF attribute value to check /// /// \returns NumErrors The number of errors occurred during verification of - /// attributes' forms in a .debug_info section unit + /// attributes' forms in a unit unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue); /// Verifies the all valid references that were found when iterating through @@ -199,7 +220,7 @@ private: /// CU relative and absolute references. /// /// \returns NumErrors The number of errors occurred during verification of - /// references for the .debug_info section + /// references for the .debug_info and .debug_types sections unsigned verifyDebugInfoReferences(); /// Verify the DW_AT_stmt_list encoding and value and ensure that no @@ -268,8 +289,8 @@ private: public: DWARFVerifier(raw_ostream &S, DWARFContext &D, - DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE()) - : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)) {} + DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE()); + /// Verify the information in any of the following sections, if available: /// .debug_abbrev, debug_abbrev.dwo /// @@ -280,12 +301,12 @@ public: /// false otherwise. bool handleDebugAbbrev(); - /// Verify the information in the .debug_info section. + /// Verify the information in the .debug_info and .debug_types sections. /// - /// Any errors are reported to the stream that was this object was + /// Any errors are reported to the stream that this object was /// constructed with. /// - /// \returns true if the .debug_info verifies successfully, false otherwise. + /// \returns true if all sections verify successfully, false otherwise. bool handleDebugInfo(); /// Verify the information in the .debug_line section. diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFError.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFError.h index e66aeca3cd4..5c043a7837b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFError.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFError.h @@ -24,22 +24,28 @@ enum class msf_error_code { invalid_format, block_in_use }; +} // namespace msf +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} // namespace std + +namespace llvm { +namespace msf { +const std::error_category &MSFErrCategory(); + +inline std::error_code make_error_code(msf_error_code E) { + return std::error_code(static_cast(E), MSFErrCategory()); +} /// Base class for errors originating when parsing raw PDB files -class MSFError : public ErrorInfo { +class MSFError : public ErrorInfo { public: + using ErrorInfo::ErrorInfo; // inherit constructors + MSFError(const Twine &S) : ErrorInfo(S, msf_error_code::unspecified) {} static char ID; - MSFError(msf_error_code C); - MSFError(const std::string &Context); - MSFError(msf_error_code C, const std::string &Context); - - void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - msf_error_code Code; }; } // namespace msf } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h index 9713dce362d..ac7f19637ab 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -43,11 +43,6 @@ public: void reset() override { Enumerator->reset(); } - ConcreteSymbolEnumerator *clone() const override { - std::unique_ptr WrappedClone(Enumerator->clone()); - return new ConcreteSymbolEnumerator(std::move(WrappedClone)); - } - private: std::unique_ptr Enumerator; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h index 930bea6060b..881d7329ab6 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h @@ -24,7 +24,6 @@ public: llvm::Optional getItemAtIndex(uint32_t Index) const override; bool getNext(RecordType &Record) override; void reset() override; - DIADataStream *clone() const override; private: CComPtr StreamData; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h index ffae6645e94..1f129052d03 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h @@ -27,7 +27,6 @@ public: ChildTypePtr getChildAtIndex(uint32_t Index) const override; ChildTypePtr getNext() override; void reset() override; - DIAEnumDebugStreams *clone() const override; private: CComPtr Enumerator; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h new file mode 100644 index 00000000000..f3b02f07e64 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h @@ -0,0 +1,36 @@ +//==- DIAEnumFrameData.h --------------------------------------- -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMFRAMEDATA_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMFRAMEDATA_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBFrameData.h" + +namespace llvm { +namespace pdb { + +class DIAEnumFrameData : public IPDBEnumChildren { +public: + explicit DIAEnumFrameData(CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + +private: + CComPtr Enumerator; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h index 39490a4b220..4669a8d3119 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h @@ -16,22 +16,18 @@ namespace llvm { namespace pdb { -class DIASession; class DIAEnumInjectedSources : public IPDBEnumChildren { public: explicit DIAEnumInjectedSources( - const DIASession &PDBSession, CComPtr DiaEnumerator); uint32_t getChildCount() const override; ChildTypePtr getChildAtIndex(uint32_t Index) const override; ChildTypePtr getNext() override; void reset() override; - DIAEnumInjectedSources *clone() const override; private: - const DIASession &Session; CComPtr Enumerator; }; } // namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h index 08f0de124ed..f1cb6268a26 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h @@ -26,7 +26,6 @@ public: ChildTypePtr getChildAtIndex(uint32_t Index) const override; ChildTypePtr getNext() override; void reset() override; - DIAEnumLineNumbers *clone() const override; private: CComPtr Enumerator; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h index 52c9563b5d5..ac2ae317d26 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h @@ -28,7 +28,6 @@ public: ChildTypePtr getChildAtIndex(uint32_t Index) const override; ChildTypePtr getNext() override; void reset() override; - DIAEnumSectionContribs *clone() const override; private: const DIASession &Session; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h index e69d18f5ba3..dac3df06a17 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h @@ -27,7 +27,6 @@ public: ChildTypePtr getChildAtIndex(uint32_t Index) const override; ChildTypePtr getNext() override; void reset() override; - DIAEnumSourceFiles *clone() const override; private: const DIASession &Session; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h index f779cd1f4be..9689859ae0f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h @@ -27,7 +27,6 @@ public: std::unique_ptr getChildAtIndex(uint32_t Index) const override; std::unique_ptr getNext() override; void reset() override; - DIAEnumSymbols *clone() const override; private: const DIASession &Session; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h index 926fcfe6964..f4f856ebb6f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h @@ -26,7 +26,6 @@ public: std::unique_ptr getChildAtIndex(uint32_t Index) const override; std::unique_ptr getNext() override; void reset() override; - DIAEnumTables *clone() const override; private: CComPtr Enumerator; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h index 35a39a0df5c..2b33a65a0a1 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAError.h @@ -23,23 +23,29 @@ enum class dia_error_code { already_loaded, debug_info_mismatch, }; +} // namespace pdb +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} // namespace std + +namespace llvm { +namespace pdb { +const std::error_category &DIAErrCategory(); + +inline std::error_code make_error_code(dia_error_code E) { + return std::error_code(static_cast(E), DIAErrCategory()); +} /// Base class for errors originating in DIA SDK, e.g. COM calls -class DIAError : public ErrorInfo { +class DIAError : public ErrorInfo { public: + using ErrorInfo::ErrorInfo; + DIAError(const Twine &S) : ErrorInfo(S, dia_error_code::unspecified) {} static char ID; - DIAError(dia_error_code C); - DIAError(StringRef Context); - DIAError(dia_error_code C, StringRef Context); - - void log(raw_ostream &OS) const override; - StringRef getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - dia_error_code Code; }; -} -} +} // namespace pdb +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h new file mode 100644 index 00000000000..0ce6cfc9303 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h @@ -0,0 +1,39 @@ +//===- DIAFrameData.h - DIA Impl. of IPDBFrameData ---------------- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAFRAMEDATA_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAFRAMEDATA_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBFrameData.h" + +namespace llvm { +namespace pdb { + +class DIASession; + +class DIAFrameData : public IPDBFrameData { +public: + explicit DIAFrameData(CComPtr DiaFrameData); + + uint32_t getAddressOffset() const override; + uint32_t getAddressSection() const override; + uint32_t getLengthBlock() const override; + std::string getProgram() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + +private: + CComPtr FrameData; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h index dfb35647055..5d4f855c63c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -20,7 +20,8 @@ class DIARawSymbol : public IPDBRawSymbol { public: DIARawSymbol(const DIASession &PDBSession, CComPtr DiaSymbol); - void dump(raw_ostream &OS, int Indent) const override; + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; CComPtr getDiaSymbol() const { return Symbol; } @@ -63,25 +64,25 @@ public: uint32_t getAddressOffset() const override; uint32_t getAddressSection() const override; uint32_t getAge() const override; - uint32_t getArrayIndexTypeId() const override; + SymIndexId getArrayIndexTypeId() const override; uint32_t getBaseDataOffset() const override; uint32_t getBaseDataSlot() const override; - uint32_t getBaseSymbolId() const override; + SymIndexId getBaseSymbolId() const override; PDB_BuiltinType getBuiltinType() const override; uint32_t getBitPosition() const override; PDB_CallingConv getCallingConvention() const override; - uint32_t getClassParentId() const override; + SymIndexId getClassParentId() const override; std::string getCompilerName() const override; uint32_t getCount() const override; uint32_t getCountLiveRanges() const override; PDB_Lang getLanguage() const override; - uint32_t getLexicalParentId() const override; + SymIndexId getLexicalParentId() const override; std::string getLibraryName() const override; uint32_t getLiveRangeStartAddressOffset() const override; uint32_t getLiveRangeStartAddressSection() const override; uint32_t getLiveRangeStartRelativeVirtualAddress() const override; codeview::RegisterId getLocalBasePointerRegisterId() const override; - uint32_t getLowerBoundId() const override; + SymIndexId getLowerBoundId() const override; uint32_t getMemorySpaceKind() const override; std::string getName() const override; uint32_t getNumberOfAcceleratorPointerTags() const override; @@ -91,7 +92,7 @@ public: uint32_t getNumberOfRows() const override; std::string getObjectFileName() const override; uint32_t getOemId() const override; - uint32_t getOemSymbolId() const override; + SymIndexId getOemSymbolId() const override; uint32_t getOffsetInUdt() const override; PDB_Cpu getPlatform() const override; uint32_t getRank() const override; @@ -105,9 +106,9 @@ public: std::string getSourceFileName() const override; std::unique_ptr getSrcLineOnTypeDefn() const override; uint32_t getStride() const override; - uint32_t getSubTypeId() const override; + SymIndexId getSubTypeId() const override; std::string getSymbolsFileName() const override; - uint32_t getSymIndexId() const override; + SymIndexId getSymIndexId() const override; uint32_t getTargetOffset() const override; uint32_t getTargetRelativeVirtualAddress() const override; uint64_t getTargetVirtualAddress() const override; @@ -115,16 +116,16 @@ public: uint32_t getTextureSlot() const override; uint32_t getTimeStamp() const override; uint32_t getToken() const override; - uint32_t getTypeId() const override; + SymIndexId getTypeId() const override; uint32_t getUavSlot() const override; std::string getUndecoratedName() const override; std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const override; - uint32_t getUnmodifiedTypeId() const override; - uint32_t getUpperBoundId() const override; + SymIndexId getUnmodifiedTypeId() const override; + SymIndexId getUpperBoundId() const override; Variant getValue() const override; uint32_t getVirtualBaseDispIndex() const override; uint32_t getVirtualBaseOffset() const override; - uint32_t getVirtualTableShapeId() const override; + SymIndexId getVirtualTableShapeId() const override; std::unique_ptr getVirtualBaseTableType() const override; PDB_DataKind getDataKind() const override; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h index a6365943938..592e061a8d8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -32,7 +32,7 @@ public: uint64_t getLoadAddress() const override; bool setLoadAddress(uint64_t Address) override; std::unique_ptr getGlobalScope() override; - std::unique_ptr getSymbolById(uint32_t SymbolId) const override; + std::unique_ptr getSymbolById(SymIndexId SymbolId) const override; bool addressForVA(uint64_t VA, uint32_t &Section, uint32_t &Offset) const override; @@ -85,6 +85,7 @@ public: std::unique_ptr getSectionContribs() const override; + std::unique_ptr getFrameData() const override; private: CComPtr Session; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h b/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h index 03205a986f1..997f13f5f30 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/GenericError.h @@ -16,29 +16,37 @@ namespace llvm { namespace pdb { -enum class generic_error_code { - invalid_path = 1, +enum class pdb_error_code { + invalid_utf8_path = 1, dia_sdk_not_present, - type_server_not_found, + dia_failed_loading, + signature_out_of_date, + external_cmdline_ref, unspecified, }; +} // namespace pdb +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} // namespace std + +namespace llvm { +namespace pdb { +const std::error_category &PDBErrCategory(); + +inline std::error_code make_error_code(pdb_error_code E) { + return std::error_code(static_cast(E), PDBErrCategory()); +} /// Base class for errors originating when parsing raw PDB files -class GenericError : public ErrorInfo { +class PDBError : public ErrorInfo { public: + using ErrorInfo::ErrorInfo; // inherit constructors + PDBError(const Twine &S) : ErrorInfo(S, pdb_error_code::unspecified) {} static char ID; - GenericError(generic_error_code C); - GenericError(StringRef Context); - GenericError(generic_error_code C, StringRef Context); - - void log(raw_ostream &OS) const override; - StringRef getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - generic_error_code Code; }; -} -} +} // namespace pdb +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBDataStream.h index 67b5a06d7c5..0d7a286a11a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBDataStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBDataStream.h @@ -32,7 +32,6 @@ public: virtual Optional getItemAtIndex(uint32_t Index) const = 0; virtual bool getNext(RecordType &Record) = 0; virtual void reset() = 0; - virtual IPDBDataStream *clone() const = 0; }; } // end namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h index b6b7d95f628..7017f2600e9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H #define LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H +#include #include #include @@ -27,7 +28,19 @@ public: virtual ChildTypePtr getChildAtIndex(uint32_t Index) const = 0; virtual ChildTypePtr getNext() = 0; virtual void reset() = 0; - virtual MyType *clone() const = 0; +}; + +template +class NullEnumerator : public IPDBEnumChildren { + virtual uint32_t getChildCount() const override { return 0; } + virtual std::unique_ptr + getChildAtIndex(uint32_t Index) const override { + return nullptr; + } + virtual std::unique_ptr getNext() override { + return nullptr; + } + virtual void reset() override {} }; } // end namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBFrameData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBFrameData.h new file mode 100644 index 00000000000..74679215b88 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBFrameData.h @@ -0,0 +1,36 @@ +//===- IPDBFrameData.h - base interface for frame data ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBFRAMEDATA_H +#define LLVM_DEBUGINFO_PDB_IPDBFRAMEDATA_H + +#include +#include + +namespace llvm { +namespace pdb { + +/// IPDBFrameData defines an interface used to represent a frame data of some +/// code block. +class IPDBFrameData { +public: + virtual ~IPDBFrameData(); + + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getLengthBlock() const = 0; + virtual std::string getProgram() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h index bcb2eaa3563..7c818d7cade 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -11,6 +11,7 @@ #define LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H #include "PDBTypes.h" +#include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" @@ -21,9 +22,26 @@ class raw_ostream; namespace pdb { +class IPDBSession; class PDBSymbolTypeVTable; class PDBSymbolTypeVTableShape; +enum class PdbSymbolIdField : uint32_t { + None = 0, + SymIndexId = 1 << 0, + LexicalParent = 1 << 1, + ClassParent = 1 << 2, + Type = 1 << 3, + UnmodifiedType = 1 << 4, + All = 0xFFFFFFFF, + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ All) +}; + +void dumpSymbolIdField(raw_ostream &OS, StringRef Name, SymIndexId Value, + int Indent, const IPDBSession &Session, + PdbSymbolIdField FieldId, PdbSymbolIdField ShowFlags, + PdbSymbolIdField RecurseFlags); + /// IPDBRawSymbol defines an interface used to represent an arbitrary symbol. /// It exposes a monolithic interface consisting of accessors for the union of /// all properties that are valid for any symbol type. This interface is then @@ -33,7 +51,8 @@ class IPDBRawSymbol { public: virtual ~IPDBRawSymbol(); - virtual void dump(raw_ostream &OS, int Indent) const = 0; + virtual void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const = 0; virtual std::unique_ptr findChildren(PDB_SymType Type) const = 0; @@ -74,26 +93,26 @@ public: virtual uint32_t getAddressOffset() const = 0; virtual uint32_t getAddressSection() const = 0; virtual uint32_t getAge() const = 0; - virtual uint32_t getArrayIndexTypeId() const = 0; + virtual SymIndexId getArrayIndexTypeId() const = 0; virtual uint32_t getBaseDataOffset() const = 0; virtual uint32_t getBaseDataSlot() const = 0; - virtual uint32_t getBaseSymbolId() const = 0; + virtual SymIndexId getBaseSymbolId() const = 0; virtual PDB_BuiltinType getBuiltinType() const = 0; virtual uint32_t getBitPosition() const = 0; virtual PDB_CallingConv getCallingConvention() const = 0; - virtual uint32_t getClassParentId() const = 0; + virtual SymIndexId getClassParentId() const = 0; virtual std::string getCompilerName() const = 0; virtual uint32_t getCount() const = 0; virtual uint32_t getCountLiveRanges() const = 0; virtual void getFrontEndVersion(VersionInfo &Version) const = 0; virtual PDB_Lang getLanguage() const = 0; - virtual uint32_t getLexicalParentId() const = 0; + virtual SymIndexId getLexicalParentId() const = 0; virtual std::string getLibraryName() const = 0; virtual uint32_t getLiveRangeStartAddressOffset() const = 0; virtual uint32_t getLiveRangeStartAddressSection() const = 0; virtual uint32_t getLiveRangeStartRelativeVirtualAddress() const = 0; virtual codeview::RegisterId getLocalBasePointerRegisterId() const = 0; - virtual uint32_t getLowerBoundId() const = 0; + virtual SymIndexId getLowerBoundId() const = 0; virtual uint32_t getMemorySpaceKind() const = 0; virtual std::string getName() const = 0; virtual uint32_t getNumberOfAcceleratorPointerTags() const = 0; @@ -103,7 +122,7 @@ public: virtual uint32_t getNumberOfRows() const = 0; virtual std::string getObjectFileName() const = 0; virtual uint32_t getOemId() const = 0; - virtual uint32_t getOemSymbolId() const = 0; + virtual SymIndexId getOemSymbolId() const = 0; virtual uint32_t getOffsetInUdt() const = 0; virtual PDB_Cpu getPlatform() const = 0; virtual uint32_t getRank() const = 0; @@ -118,9 +137,9 @@ public: virtual std::unique_ptr getSrcLineOnTypeDefn() const = 0; virtual uint32_t getStride() const = 0; - virtual uint32_t getSubTypeId() const = 0; + virtual SymIndexId getSubTypeId() const = 0; virtual std::string getSymbolsFileName() const = 0; - virtual uint32_t getSymIndexId() const = 0; + virtual SymIndexId getSymIndexId() const = 0; virtual uint32_t getTargetOffset() const = 0; virtual uint32_t getTargetRelativeVirtualAddress() const = 0; virtual uint64_t getTargetVirtualAddress() const = 0; @@ -128,18 +147,18 @@ public: virtual uint32_t getTextureSlot() const = 0; virtual uint32_t getTimeStamp() const = 0; virtual uint32_t getToken() const = 0; - virtual uint32_t getTypeId() const = 0; + virtual SymIndexId getTypeId() const = 0; virtual uint32_t getUavSlot() const = 0; virtual std::string getUndecoratedName() const = 0; virtual std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const = 0; - virtual uint32_t getUnmodifiedTypeId() const = 0; - virtual uint32_t getUpperBoundId() const = 0; + virtual SymIndexId getUnmodifiedTypeId() const = 0; + virtual SymIndexId getUpperBoundId() const = 0; virtual Variant getValue() const = 0; virtual uint32_t getVirtualBaseDispIndex() const = 0; virtual uint32_t getVirtualBaseOffset() const = 0; virtual std::unique_ptr getVirtualBaseTableType() const = 0; - virtual uint32_t getVirtualTableShapeId() const = 0; + virtual SymIndexId getVirtualTableShapeId() const = 0; virtual PDB_DataKind getDataKind() const = 0; virtual PDB_SymType getSymTag() const = 0; virtual codeview::GUID getGuid() const = 0; @@ -237,6 +256,8 @@ public: virtual std::string getUnused() const = 0; }; +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + } // namespace pdb } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h index 88ec517bc4a..88fd02c0a34 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -30,7 +30,8 @@ public: virtual uint64_t getLoadAddress() const = 0; virtual bool setLoadAddress(uint64_t Address) = 0; virtual std::unique_ptr getGlobalScope() = 0; - virtual std::unique_ptr getSymbolById(uint32_t SymbolId) const = 0; + virtual std::unique_ptr + getSymbolById(SymIndexId SymbolId) const = 0; virtual bool addressForVA(uint64_t VA, uint32_t &Section, uint32_t &Offset) const = 0; @@ -38,7 +39,7 @@ public: uint32_t &Offset) const = 0; template - std::unique_ptr getConcreteSymbolById(uint32_t SymbolId) const { + std::unique_ptr getConcreteSymbolById(SymIndexId SymbolId) const { return unique_dyn_cast_or_null(getSymbolById(SymbolId)); } @@ -90,6 +91,9 @@ public: virtual std::unique_ptr getSectionContribs() const = 0; + + virtual std::unique_ptr + getFrameData() const = 0; }; } // namespace pdb } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index ce4d0791775..ac7f741afef 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -51,6 +51,7 @@ public: void setObjFileName(StringRef Name); void setFirstSectionContrib(const SectionContrib &SC); void addSymbol(codeview::CVSymbol Symbol); + void addSymbolsInBulk(ArrayRef BulkSymbols); void addDebugSubsection(std::shared_ptr Subsection); @@ -91,7 +92,7 @@ private: std::string ModuleName; std::string ObjFileName; std::vector SourceFiles; - std::vector Symbols; + std::vector> Symbols; std::vector> C13Builders; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h index 280615bdb50..a3ca607efbe 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -78,7 +78,7 @@ public: const DbiModuleList &modules() const; - FixedStreamArray getSectionHeaders(); + FixedStreamArray getSectionHeaders() const; FixedStreamArray getFpoRecords(); diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h index 51befcdac77..b538de57667 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -15,6 +15,7 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/Support/Error.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" @@ -24,11 +25,15 @@ #include "llvm/Support/Endian.h" namespace llvm { +namespace codeview { +struct FrameData; +} namespace msf { class MSFBuilder; } namespace object { struct coff_section; +struct FpoData; } namespace pdb { class DbiStream; @@ -65,6 +70,8 @@ public: void setGlobalsStreamIndex(uint32_t Index); void setPublicsStreamIndex(uint32_t Index); void setSymbolRecordStreamIndex(uint32_t Index); + void addNewFpoData(const codeview::FrameData &FD); + void addOldFpoData(const object::FpoData &Fpo); Expected addModuleInfo(StringRef ModuleName); Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File); @@ -84,7 +91,8 @@ public: private: struct DebugStream { - ArrayRef Data; + std::function WriteFn; + uint32_t Size = 0; uint16_t StreamNumber = kInvalidStreamIndex; }; @@ -117,6 +125,9 @@ private: std::vector> ModiList; + Optional NewFpoData; + std::vector OldFpoData; + StringMap SourceFileNames; PDBStringTableBuilder ECNamesBuilder; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h index 1a4f89d607d..4c39ca762b5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h @@ -61,7 +61,6 @@ public: void addGlobalSymbol(const codeview::ProcRefSym &Sym); void addGlobalSymbol(const codeview::DataSym &Sym); void addGlobalSymbol(const codeview::ConstantSym &Sym); - void addGlobalSymbol(const codeview::UDTSym &Sym); void addGlobalSymbol(const codeview::CVSymbol &Sym); private: diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h index dd04b5c5681..7f84564ee98 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h @@ -10,18 +10,20 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H #define LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H +#include "llvm/ADT/iterator.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Error.h" -#include "llvm/ADT/iterator.h" namespace llvm { namespace pdb { class DbiStream; class PDBFile; +class SymbolStream; /// Iterator over hash records producing symbol record offsets. Abstracts away /// the fact that symbol record offsets on disk are off-by-one. @@ -50,8 +52,9 @@ class GSIHashTable { public: const GSIHashHeader *HashHdr; FixedStreamArray HashRecords; - ArrayRef HashBitmap; + FixedStreamArray HashBitmap; FixedStreamArray HashBuckets; + std::array BucketMap; Error read(BinaryStreamReader &Reader); @@ -72,6 +75,9 @@ public: const GSIHashTable &getGlobalsTable() const { return GlobalsTable; } Error reload(); + std::vector> + findRecordsByName(StringRef Name, const SymbolStream &Symbols) const; + private: GSIHashTable GlobalsTable; std::unique_ptr Stream; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h index 419e8ada06f..101127a355f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h @@ -35,11 +35,18 @@ public: InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete; void setVersion(PdbRaw_ImplVer V); + void addFeature(PdbRaw_FeatureSig Sig); + + // If this is true, the PDB contents are hashed and this hash is used as + // PDB GUID and as Signature. The age is always 1. + void setHashPDBContentsToGUID(bool B); + + // These only have an effect if hashPDBContentsToGUID() is false. void setSignature(uint32_t S); void setAge(uint32_t A); void setGuid(codeview::GUID G); - void addFeature(PdbRaw_FeatureSig Sig); + bool hashPDBContentsToGUID() const { return HashPDBContentsToGUID; } uint32_t getAge() const { return Age; } codeview::GUID getGuid() const { return Guid; } Optional getSignature() const { return Signature; } @@ -60,6 +67,8 @@ private: Optional Signature; codeview::GUID Guid; + bool HashPDBContentsToGUID = false; + NamedStreamMap &NamedStreams; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h index efc25e0559b..8d590df288f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -15,6 +15,7 @@ #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Error.h" #include @@ -43,6 +44,8 @@ public: symbols(bool *HadError) const; const codeview::CVSymbolArray &getSymbolArray() const { return SymbolArray; } + const codeview::CVSymbolArray + getSymbolArrayForScope(uint32_t ScopeBegin) const; BinarySubstreamRef getSymbolsSubstream() const; BinarySubstreamRef getC11LinesSubstream() const; @@ -51,6 +54,8 @@ public: ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = delete; + codeview::CVSymbol readSymbolAtOffset(uint32_t Offset) const; + iterator_range subsections() const; codeview::DebugSubsectionArray getSubsectionsArray() const { return Subsections; @@ -64,7 +69,7 @@ public: findChecksumsSubsection() const; private: - const DbiModuleDescriptor &Mod; + DbiModuleDescriptor Mod; uint32_t Signature; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h index bd5c09e5ff7..3cd46550304 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h @@ -21,11 +21,12 @@ public: NativeCompilandSymbol(NativeSession &Session, SymIndexId SymbolId, DbiModuleDescriptor MI); - std::unique_ptr clone() const override; + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; PDB_SymType getSymTag() const override; bool isEditAndContinueEnabled() const override; - uint32_t getLexicalParentId() const override; + SymIndexId getLexicalParentId() const override; std::string getLibraryName() const override; std::string getName() const override; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h new file mode 100644 index 00000000000..4442a1ec41f --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h @@ -0,0 +1,43 @@ +//==- NativeEnumGlobals.h - Native Global Enumerator impl --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMGLOBALS_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMGLOBALS_H + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +#include + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeEnumGlobals : public IPDBEnumChildren { +public: + NativeEnumGlobals(NativeSession &Session, + std::vector Kinds); + + uint32_t getChildCount() const override; + std::unique_ptr getChildAtIndex(uint32_t Index) const override; + std::unique_ptr getNext() override; + void reset() override; + +private: + std::vector MatchOffsets; + uint32_t Index; + NativeSession &Session; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h index 6aa1460dbb4..c268641a100 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h @@ -11,28 +11,23 @@ #define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMMODULES_H #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" namespace llvm { namespace pdb { -class DbiModuleList; class NativeSession; class NativeEnumModules : public IPDBEnumChildren { public: - NativeEnumModules(NativeSession &Session, const DbiModuleList &Modules, - uint32_t Index = 0); + NativeEnumModules(NativeSession &Session, uint32_t Index = 0); uint32_t getChildCount() const override; std::unique_ptr getChildAtIndex(uint32_t Index) const override; std::unique_ptr getNext() override; void reset() override; - NativeEnumModules *clone() const override; private: NativeSession &Session; - const DbiModuleList &Modules; uint32_t Index; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h deleted file mode 100644 index 41b7b78b8d8..00000000000 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h +++ /dev/null @@ -1,60 +0,0 @@ -//===- NativeEnumSymbol.h - info about enum type ----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H -#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H - -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" -#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" -#include "llvm/DebugInfo/PDB/Native/NativeSession.h" - -namespace llvm { -namespace pdb { - -class NativeEnumSymbol : public NativeRawSymbol, - public codeview::TypeVisitorCallbacks { -public: - NativeEnumSymbol(NativeSession &Session, SymIndexId Id, - const codeview::CVType &CV); - ~NativeEnumSymbol() override; - - std::unique_ptr clone() const override; - - std::unique_ptr - findChildren(PDB_SymType Type) const override; - - Error visitKnownRecord(codeview::CVType &CVR, - codeview::EnumRecord &Record) override; - Error visitKnownMember(codeview::CVMemberRecord &CVM, - codeview::EnumeratorRecord &Record) override; - - PDB_SymType getSymTag() const override; - uint32_t getClassParentId() const override; - uint32_t getUnmodifiedTypeId() const override; - bool hasConstructor() const override; - bool hasAssignmentOperator() const override; - bool hasCastOperator() const override; - uint64_t getLength() const override; - std::string getName() const override; - bool isNested() const override; - bool hasOverloadedOperator() const override; - bool isPacked() const override; - bool isScoped() const override; - uint32_t getTypeId() const override; - -protected: - codeview::CVType CV; - codeview::EnumRecord Record; -}; - -} // namespace pdb -} // namespace llvm - -#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h index e0a5c8d9ad8..f8ac1655dc6 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h @@ -26,23 +26,20 @@ class NativeEnumTypes : public IPDBEnumChildren { public: NativeEnumTypes(NativeSession &Session, codeview::LazyRandomTypeCollection &TypeCollection, - codeview::TypeLeafKind Kind); + std::vector Kinds); + + NativeEnumTypes(NativeSession &Session, + std::vector Indices); uint32_t getChildCount() const override; std::unique_ptr getChildAtIndex(uint32_t Index) const override; std::unique_ptr getNext() override; void reset() override; - NativeEnumTypes *clone() const override; private: - NativeEnumTypes(NativeSession &Session, - const std::vector &Matches, - codeview::TypeLeafKind Kind); - std::vector Matches; uint32_t Index; NativeSession &Session; - codeview::TypeLeafKind Kind; }; } // namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h index 587c7ff2b09..f4030da1d02 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h @@ -16,11 +16,14 @@ namespace llvm { namespace pdb { -class NativeExeSymbol : public NativeRawSymbol { -public: - NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId); +class DbiStream; - std::unique_ptr clone() const override; +class NativeExeSymbol : public NativeRawSymbol { + // EXE symbol is the authority on the various symbol types. + DbiStream *Dbi = nullptr; + +public: + NativeExeSymbol(NativeSession &Session, SymIndexId Id); std::unique_ptr findChildren(PDB_SymType Type) const override; @@ -30,9 +33,6 @@ public: codeview::GUID getGuid() const override; bool hasCTypes() const override; bool hasPrivateSymbols() const override; - -private: - PDBFile &File; }; } // namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h index 5b70ecfa205..6505a7d3957 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h @@ -19,15 +19,16 @@ namespace pdb { class NativeSession; -typedef uint32_t SymIndexId; - class NativeRawSymbol : public IPDBRawSymbol { + friend class SymbolCache; + virtual void initialize() {} + public: - NativeRawSymbol(NativeSession &PDBSession, SymIndexId SymbolId); + NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag, + SymIndexId SymbolId); - virtual std::unique_ptr clone() const = 0; - - void dump(raw_ostream &OS, int Indent) const override; + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; std::unique_ptr findChildren(PDB_SymType Type) const override; @@ -68,25 +69,25 @@ public: uint32_t getAddressOffset() const override; uint32_t getAddressSection() const override; uint32_t getAge() const override; - uint32_t getArrayIndexTypeId() const override; + SymIndexId getArrayIndexTypeId() const override; uint32_t getBaseDataOffset() const override; uint32_t getBaseDataSlot() const override; - uint32_t getBaseSymbolId() const override; + SymIndexId getBaseSymbolId() const override; PDB_BuiltinType getBuiltinType() const override; uint32_t getBitPosition() const override; PDB_CallingConv getCallingConvention() const override; - uint32_t getClassParentId() const override; + SymIndexId getClassParentId() const override; std::string getCompilerName() const override; uint32_t getCount() const override; uint32_t getCountLiveRanges() const override; PDB_Lang getLanguage() const override; - uint32_t getLexicalParentId() const override; + SymIndexId getLexicalParentId() const override; std::string getLibraryName() const override; uint32_t getLiveRangeStartAddressOffset() const override; uint32_t getLiveRangeStartAddressSection() const override; uint32_t getLiveRangeStartRelativeVirtualAddress() const override; codeview::RegisterId getLocalBasePointerRegisterId() const override; - uint32_t getLowerBoundId() const override; + SymIndexId getLowerBoundId() const override; uint32_t getMemorySpaceKind() const override; std::string getName() const override; uint32_t getNumberOfAcceleratorPointerTags() const override; @@ -96,7 +97,7 @@ public: uint32_t getNumberOfRows() const override; std::string getObjectFileName() const override; uint32_t getOemId() const override; - uint32_t getOemSymbolId() const override; + SymIndexId getOemSymbolId() const override; uint32_t getOffsetInUdt() const override; PDB_Cpu getPlatform() const override; uint32_t getRank() const override; @@ -110,9 +111,9 @@ public: std::string getSourceFileName() const override; std::unique_ptr getSrcLineOnTypeDefn() const override; uint32_t getStride() const override; - uint32_t getSubTypeId() const override; + SymIndexId getSubTypeId() const override; std::string getSymbolsFileName() const override; - uint32_t getSymIndexId() const override; + SymIndexId getSymIndexId() const override; uint32_t getTargetOffset() const override; uint32_t getTargetRelativeVirtualAddress() const override; uint64_t getTargetVirtualAddress() const override; @@ -120,16 +121,16 @@ public: uint32_t getTextureSlot() const override; uint32_t getTimeStamp() const override; uint32_t getToken() const override; - uint32_t getTypeId() const override; + SymIndexId getTypeId() const override; uint32_t getUavSlot() const override; std::string getUndecoratedName() const override; std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const override; - uint32_t getUnmodifiedTypeId() const override; - uint32_t getUpperBoundId() const override; + SymIndexId getUnmodifiedTypeId() const override; + SymIndexId getUpperBoundId() const override; Variant getValue() const override; uint32_t getVirtualBaseDispIndex() const override; uint32_t getVirtualBaseOffset() const override; - uint32_t getVirtualTableShapeId() const override; + SymIndexId getVirtualTableShapeId() const override; std::unique_ptr getVirtualBaseTableType() const override; PDB_DataKind getDataKind() const override; @@ -230,6 +231,7 @@ public: protected: NativeSession &Session; + PDB_SymType Tag; SymIndexId SymbolId; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h index aff7ef2f8f2..4878e47d312 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -15,9 +15,8 @@ #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" -#include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" @@ -25,6 +24,7 @@ namespace llvm { class MemoryBuffer; namespace pdb { class PDBFile; +class NativeExeSymbol; class NativeSession : public IPDBSession { public: @@ -37,21 +37,10 @@ public: static Error createFromExe(StringRef Path, std::unique_ptr &Session); - std::unique_ptr - createCompilandSymbol(DbiModuleDescriptor MI); - - std::unique_ptr - createEnumSymbol(codeview::TypeIndex Index); - - std::unique_ptr - createTypeEnumerator(codeview::TypeLeafKind Kind); - - SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); - uint64_t getLoadAddress() const override; bool setLoadAddress(uint64_t Address) override; std::unique_ptr getGlobalScope() override; - std::unique_ptr getSymbolById(uint32_t SymbolId) const override; + std::unique_ptr getSymbolById(SymIndexId SymbolId) const override; bool addressForVA(uint64_t VA, uint32_t &Section, uint32_t &Offset) const override; @@ -104,14 +93,23 @@ public: std::unique_ptr getSectionContribs() const override; + std::unique_ptr getFrameData() const override; + PDBFile &getPDBFile() { return *Pdb; } const PDBFile &getPDBFile() const { return *Pdb; } + NativeExeSymbol &getNativeGlobalScope() const; + SymbolCache &getSymbolCache() { return Cache; } + const SymbolCache &getSymbolCache() const { return Cache; } + private: + void initializeExeSymbol(); + std::unique_ptr Pdb; std::unique_ptr Allocator; - std::vector> SymbolCache; - DenseMap TypeIndexToSymbolId; + + SymbolCache Cache; + SymIndexId ExeSymbol = 0; }; } // namespace pdb } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h new file mode 100644 index 00000000000..acc5eb8ff2c --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h @@ -0,0 +1,51 @@ +//===- NativeSymbolEnumerator.h - info about enumerator values --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVESYMBOLENUMERATOR_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESYMBOLENUMERATOR_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { +class NativeTypeEnum; + +class NativeSymbolEnumerator : public NativeRawSymbol { +public: + NativeSymbolEnumerator(NativeSession &Session, SymIndexId Id, + const NativeTypeEnum &Parent, + codeview::EnumeratorRecord Record); + + ~NativeSymbolEnumerator() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + SymIndexId getClassParentId() const override; + SymIndexId getLexicalParentId() const override; + std::string getName() const override; + SymIndexId getTypeId() const override; + PDB_DataKind getDataKind() const override; + PDB_LocType getLocationType() const override; + bool isConstType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + Variant getValue() const override; + +protected: + const NativeTypeEnum &Parent; + codeview::EnumeratorRecord Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h new file mode 100644 index 00000000000..10e68e6df45 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h @@ -0,0 +1,50 @@ +//===- NativeTypeArray.h ------------------------------------------ C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEARRAY_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEARRAY_H + +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" + +namespace llvm { +namespace pdb { + +class NativeSession; + +class NativeTypeArray : public NativeRawSymbol { +public: + NativeTypeArray(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::ArrayRecord Record); + ~NativeTypeArray() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + SymIndexId getArrayIndexTypeId() const override; + + bool isConstType() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + + uint32_t getCount() const override; + SymIndexId getTypeId() const override; + uint64_t getLength() const override; + +protected: + codeview::ArrayRecord Record; + codeview::TypeIndex Index; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h similarity index 58% rename from contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h rename to contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h index 4f532c6e382..725dfb89222 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h @@ -1,4 +1,4 @@ -//===- NativeBuiltinSymbol.h -------------------------------------- C++ -*-===// +//===- NativeTypeBuiltin.h ---------------------------------------- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEBUILTINSYMBOL_H -#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEBUILTINSYMBOL_H +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEBUILTIN_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEBUILTIN_H #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" @@ -19,15 +19,15 @@ namespace pdb { class NativeSession; -class NativeBuiltinSymbol : public NativeRawSymbol { +class NativeTypeBuiltin : public NativeRawSymbol { public: - NativeBuiltinSymbol(NativeSession &PDBSession, SymIndexId Id, - PDB_BuiltinType T, uint64_t L); - ~NativeBuiltinSymbol() override; + NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, + codeview::ModifierOptions Mods, PDB_BuiltinType T, + uint64_t L); + ~NativeTypeBuiltin() override; - virtual std::unique_ptr clone() const override; - - void dump(raw_ostream &OS, int Indent) const override; + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; PDB_SymType getSymTag() const override; @@ -39,6 +39,7 @@ public: protected: NativeSession &Session; + codeview::ModifierOptions Mods; PDB_BuiltinType Type; uint64_t Length; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h new file mode 100644 index 00000000000..a5cbefc1811 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h @@ -0,0 +1,75 @@ +//===- NativeTypeEnum.h - info about enum type ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeBuiltin; + +class NativeTypeEnum : public NativeRawSymbol { +public: + NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::EnumRecord Record); + + NativeTypeEnum(NativeSession &Session, SymIndexId Id, + NativeTypeEnum &UnmodifiedType, + codeview::ModifierRecord Modifier); + ~NativeTypeEnum() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::unique_ptr + findChildren(PDB_SymType Type) const override; + + PDB_BuiltinType getBuiltinType() const override; + PDB_SymType getSymTag() const override; + SymIndexId getUnmodifiedTypeId() const override; + bool hasConstructor() const override; + bool hasAssignmentOperator() const override; + bool hasCastOperator() const override; + uint64_t getLength() const override; + std::string getName() const override; + bool isConstType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + bool isNested() const override; + bool hasOverloadedOperator() const override; + bool hasNestedTypes() const override; + bool isIntrinsic() const override; + bool isPacked() const override; + bool isScoped() const override; + SymIndexId getTypeId() const override; + bool isRefUdt() const override; + bool isValueUdt() const override; + bool isInterfaceUdt() const override; + + const NativeTypeBuiltin &getUnderlyingBuiltinType() const; + const codeview::EnumRecord &getEnumRecord() const { return *Record; } + +protected: + codeview::TypeIndex Index; + Optional Record; + NativeTypeEnum *UnmodifiedType = nullptr; + Optional Modifiers; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h new file mode 100644 index 00000000000..1b1b87f6581 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h @@ -0,0 +1,74 @@ +//===- NativeTypeFunctionSig.h - info about function signature ---*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEFUNCTIONSIG_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEFUNCTIONSIG_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeUDT; + +class NativeTypeFunctionSig : public NativeRawSymbol { +protected: + void initialize() override; + +public: + NativeTypeFunctionSig(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::ProcedureRecord Proc); + + NativeTypeFunctionSig(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, + codeview::MemberFunctionRecord MemberFunc); + + ~NativeTypeFunctionSig() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::unique_ptr + findChildren(PDB_SymType Type) const override; + + SymIndexId getClassParentId() const override; + PDB_CallingConv getCallingConvention() const override; + uint32_t getCount() const override; + SymIndexId getTypeId() const override; + int32_t getThisAdjust() const override; + bool hasConstructor() const override; + bool isConstType() const override; + bool isConstructorVirtualBase() const override; + bool isCxxReturnUdt() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + +private: + void initializeArgList(codeview::TypeIndex ArgListTI); + + union { + codeview::MemberFunctionRecord MemberFunc; + codeview::ProcedureRecord Proc; + }; + + SymIndexId ClassParentId = 0; + codeview::TypeIndex Index; + codeview::ArgListRecord ArgList; + bool IsMemberFunction = false; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H \ No newline at end of file diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h new file mode 100644 index 00000000000..bcb7431fecf --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h @@ -0,0 +1,61 @@ +//===- NativeTypePointer.h - info about pointer type -------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypePointer : public NativeRawSymbol { +public: + // Create a pointer record for a simple type. + NativeTypePointer(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI); + + // Create a pointer record for a non-simple type. + NativeTypePointer(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::PointerRecord PR); + ~NativeTypePointer() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + SymIndexId getClassParentId() const override; + bool isConstType() const override; + uint64_t getLength() const override; + bool isReference() const override; + bool isRValueReference() const override; + bool isPointerToDataMember() const override; + bool isPointerToMemberFunction() const override; + SymIndexId getTypeId() const override; + bool isRestrictedType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + + bool isSingleInheritance() const override; + bool isMultipleInheritance() const override; + bool isVirtualInheritance() const override; + +protected: + bool isMemberPointer() const; + codeview::TypeIndex TI; + Optional Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H \ No newline at end of file diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h new file mode 100644 index 00000000000..06eb6fcf376 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h @@ -0,0 +1,42 @@ +//===- NativeTypeTypedef.h - info about typedef ------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPETYPEDEF_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPETYPEDEF_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeTypedef : public NativeRawSymbol { +public: + // Create a pointer record for a non-simple type. + NativeTypeTypedef(NativeSession &Session, SymIndexId Id, + codeview::UDTSym Typedef); + + ~NativeTypeTypedef() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::string getName() const override; + SymIndexId getTypeId() const override; + +protected: + codeview::UDTSym Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H \ No newline at end of file diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h new file mode 100644 index 00000000000..84821d8731b --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h @@ -0,0 +1,74 @@ +//===- NativeTypeUDT.h - info about class/struct type ------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeUDT : public NativeRawSymbol { +public: + NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::ClassRecord Class); + + NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::UnionRecord Union); + + NativeTypeUDT(NativeSession &Session, SymIndexId Id, + NativeTypeUDT &UnmodifiedType, + codeview::ModifierRecord Modifier); + + ~NativeTypeUDT() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::string getName() const override; + SymIndexId getLexicalParentId() const override; + SymIndexId getUnmodifiedTypeId() const override; + SymIndexId getVirtualTableShapeId() const override; + uint64_t getLength() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool isConstType() const override; + bool hasAssignmentOperator() const override; + bool hasCastOperator() const override; + bool hasNestedTypes() const override; + bool hasOverloadedOperator() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isNested() const override; + bool isPacked() const override; + bool isRefUdt() const override; + bool isScoped() const override; + bool isValueUdt() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + +protected: + codeview::TypeIndex Index; + + Optional Class; + Optional Union; + NativeTypeUDT *UnmodifiedType = nullptr; + codeview::TagRecord *Tag = nullptr; + Optional Modifiers; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H \ No newline at end of file diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h new file mode 100644 index 00000000000..a996f34ef85 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h @@ -0,0 +1,46 @@ +//===- NativeTypeVTShape.h - info about virtual table shape ------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeVTShape : public NativeRawSymbol { +public: + // Create a pointer record for a non-simple type. + NativeTypeVTShape(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::VFTableShapeRecord SR); + + ~NativeTypeVTShape() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + bool isConstType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; + uint32_t getCount() const override; + +protected: + codeview::TypeIndex TI; + codeview::VFTableShapeRecord Record; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H \ No newline at end of file diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h index 7f9c4cf9fa8..37458749a8d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -53,7 +53,9 @@ public: PDBStringTableBuilder &getStringTableBuilder(); GSIStreamBuilder &getGsiBuilder(); - Error commit(StringRef Filename); + // If HashPDBContentsToGUID is true on the InfoStreamBuilder, Guid is filled + // with the computed PDB GUID on return. + Error commit(StringRef Filename, codeview::GUID *Guid); Expected getNamedStreamIndex(StringRef Name) const; Error addNamedStream(StringRef Name, StringRef Data); diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawError.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawError.h index 3624a7682e3..97d11b4f20d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawError.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawError.h @@ -31,23 +31,29 @@ enum class raw_error_code { stream_too_long, invalid_tpi_hash, }; +} // namespace pdb +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} // namespace std + +namespace llvm { +namespace pdb { +const std::error_category &RawErrCategory(); + +inline std::error_code make_error_code(raw_error_code E) { + return std::error_code(static_cast(E), RawErrCategory()); +} /// Base class for errors originating when parsing raw PDB files -class RawError : public ErrorInfo { +class RawError : public ErrorInfo { public: + using ErrorInfo::ErrorInfo; // inherit constructors + RawError(const Twine &S) : ErrorInfo(S, raw_error_code::unspecified) {} static char ID; - RawError(raw_error_code C); - RawError(const std::string &Context); - RawError(raw_error_code C, const std::string &Context); - - void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - raw_error_code Code; }; -} -} +} // namespace pdb +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h index 19f592d562e..8f6d6611c03 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -343,7 +343,6 @@ struct SrcHeaderBlockEntry { char Reserved[8]; }; -constexpr int I = sizeof(SrcHeaderBlockEntry); static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!"); } // namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h new file mode 100644 index 00000000000..08e1d41e6ee --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -0,0 +1,148 @@ +//==- SymbolCache.h - Cache of native symbols and ids ------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H +#define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/Support/Allocator.h" + +#include +#include + +namespace llvm { +namespace pdb { +class DbiStream; +class PDBFile; + +class SymbolCache { + NativeSession &Session; + DbiStream *Dbi = nullptr; + + /// Cache of all stable symbols, indexed by SymIndexId. Just because a + /// symbol has been parsed does not imply that it will be stable and have + /// an Id. Id allocation is an implementation, with the only guarantee + /// being that once an Id is allocated, the symbol can be assumed to be + /// cached. + std::vector> Cache; + + /// For type records from the TPI stream which have been paresd and cached, + /// stores a mapping to SymIndexId of the cached symbol. + DenseMap TypeIndexToSymbolId; + + /// For field list members which have been parsed and cached, stores a mapping + /// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the + /// cached symbol. + DenseMap, SymIndexId> + FieldListMembersToSymbolId; + + /// List of SymIndexIds for each compiland, indexed by compiland index as they + /// appear in the PDB file. + std::vector Compilands; + + /// Map from global symbol offset to SymIndexId. + DenseMap GlobalOffsetToSymbolId; + + SymIndexId createSymbolPlaceholder() { + SymIndexId Id = Cache.size(); + Cache.push_back(nullptr); + return Id; + } + + template + SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT, + Args &&... ConstructorArgs) { + CVRecordT Record; + if (auto EC = + codeview::TypeDeserializer::deserializeAs(CVT, Record)) { + consumeError(std::move(EC)); + return 0; + } + + return createSymbol( + TI, std::move(Record), std::forward(ConstructorArgs)...); + } + + SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI, + codeview::CVType CVT); + + SymIndexId createSimpleType(codeview::TypeIndex TI, + codeview::ModifierOptions Mods); + +public: + SymbolCache(NativeSession &Session, DbiStream *Dbi); + + template + SymIndexId createSymbol(Args &&... ConstructorArgs) { + SymIndexId Id = Cache.size(); + + // Initial construction must not access the cache, since it must be done + // atomically. + auto Result = llvm::make_unique( + Session, Id, std::forward(ConstructorArgs)...); + Result->SymbolId = Id; + + NativeRawSymbol *NRS = static_cast(Result.get()); + Cache.push_back(std::move(Result)); + + // After the item is in the cache, we can do further initialization which + // is then allowed to access the cache. + NRS->initialize(); + return Id; + } + + std::unique_ptr + createTypeEnumerator(codeview::TypeLeafKind Kind); + + std::unique_ptr + createTypeEnumerator(std::vector Kinds); + + std::unique_ptr + createGlobalsEnumerator(codeview::SymbolKind Kind); + + SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); + + template + SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI, + uint32_t Index, + Args &&... ConstructorArgs) { + SymIndexId SymId = Cache.size(); + std::pair Key{FieldListTI, Index}; + auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId); + if (Result.second) + SymId = + createSymbol(std::forward(ConstructorArgs)...); + else + SymId = Result.first->second; + return SymId; + } + + SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset); + + std::unique_ptr getOrCreateCompiland(uint32_t Index); + uint32_t getNumCompilands() const; + + std::unique_ptr getSymbolById(SymIndexId SymbolId) const; + + NativeRawSymbol &getNativeSymbolById(SymIndexId SymbolId) const; + + template + ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const { + return static_cast(getNativeSymbolById(SymbolId)); + } +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiHashing.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiHashing.h index c1edec7a26f..c2996ccf182 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiHashing.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiHashing.h @@ -18,6 +18,54 @@ namespace pdb { Expected hashTypeRecord(const llvm::codeview::CVType &Type); +struct TagRecordHash { + explicit TagRecordHash(codeview::ClassRecord CR, uint32_t Full, + uint32_t Forward) + : FullRecordHash(Full), ForwardDeclHash(Forward), Class(std::move(CR)) { + State = 0; + } + + explicit TagRecordHash(codeview::EnumRecord ER, uint32_t Full, + uint32_t Forward) + : FullRecordHash(Full), ForwardDeclHash(Forward), Enum(std::move(ER)) { + State = 1; + } + + explicit TagRecordHash(codeview::UnionRecord UR, uint32_t Full, + uint32_t Forward) + : FullRecordHash(Full), ForwardDeclHash(Forward), Union(std::move(UR)) { + State = 2; + } + + uint32_t FullRecordHash; + uint32_t ForwardDeclHash; + + codeview::TagRecord &getRecord() { + switch (State) { + case 0: + return Class; + case 1: + return Enum; + case 2: + return Union; + } + llvm_unreachable("unreachable!"); + } + +private: + union { + codeview::ClassRecord Class; + codeview::EnumRecord Enum; + codeview::UnionRecord Union; + }; + + uint8_t State = 0; +}; + +/// Given a CVType referring to a class, structure, union, or enum, compute +/// the hash of its forward decl and full decl. +Expected hashTagRecord(const codeview::CVType &Type); + } // end namespace pdb } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h index b77939929ec..b76576a7a26 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h @@ -58,10 +58,21 @@ public: codeview::LazyRandomTypeCollection &typeCollection() { return *Types; } + Expected + findFullDeclForForwardRef(codeview::TypeIndex ForwardRefTI) const; + + std::vector findRecordsByName(StringRef Name) const; + + codeview::CVType getType(codeview::TypeIndex Index); + BinarySubstreamRef getTypeRecordsSubstream() const; Error commit(); + void buildHashMap(); + + bool supportsTypeLookup() const; + private: PDBFile &Pdb; std::unique_ptr Stream; @@ -77,6 +88,8 @@ private: FixedStreamArray TypeIndexOffsets; HashTable HashAdjusters; + std::vector> HashMap; + const TpiStreamHeader *Header; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h index 3c9a19801f8..aaec71aa8c9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -12,6 +12,8 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/raw_ostream.h" + #include namespace llvm { @@ -24,6 +26,7 @@ using TagStats = std::unordered_map; raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value); raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv); +raw_ostream &operator<<(raw_ostream &OS, const PDB_BuiltinType &Type); raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data); raw_ostream &operator<<(raw_ostream &OS, const codeview::RegisterId &Reg); raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc); @@ -41,6 +44,15 @@ raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats); + +template +void dumpSymbolField(raw_ostream &OS, StringRef Name, T Value, int Indent) { + OS << "\n"; + OS.indent(Indent); + OS << Name << ": " << Value; +} + + } // end namespace pdb } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h index 04373463212..3a74f7c3aac 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -49,9 +49,22 @@ class IPDBRawSymbol; class IPDBSession; #define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \ +private: \ + using PDBSymbol::PDBSymbol; \ + friend class PDBSymbol; \ + \ +public: \ static const PDB_SymType Tag = TagValue; \ static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; } +#define DECLARE_PDB_SYMBOL_CUSTOM_TYPE(Condition) \ +private: \ + using PDBSymbol::PDBSymbol; \ + friend class PDBSymbol; \ + \ +public: \ + static bool classof(const PDBSymbol *S) { return Condition; } + /// PDBSymbol defines the base of the inheritance hierarchy for concrete symbol /// types (e.g. functions, executables, vtables, etc). All concrete symbol /// types inherit from PDBSymbol and expose the exact set of methods that are @@ -59,14 +72,33 @@ class IPDBSession; /// reference "Lexical and Class Hierarchy of Symbol Types": /// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx class PDBSymbol { + static std::unique_ptr createSymbol(const IPDBSession &PDBSession, + PDB_SymType Tag); + protected: - PDBSymbol(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - PDBSymbol(PDBSymbol &Symbol); + explicit PDBSymbol(const IPDBSession &PDBSession); + PDBSymbol(PDBSymbol &&Other); public: static std::unique_ptr - create(const IPDBSession &PDBSession, std::unique_ptr Symbol); + create(const IPDBSession &PDBSession, + std::unique_ptr RawSymbol); + static std::unique_ptr create(const IPDBSession &PDBSession, + IPDBRawSymbol &RawSymbol); + + template + static std::unique_ptr + createAs(const IPDBSession &PDBSession, + std::unique_ptr RawSymbol) { + std::unique_ptr S = create(PDBSession, std::move(RawSymbol)); + return unique_dyn_cast_or_null(std::move(S)); + } + template + static std::unique_ptr createAs(const IPDBSession &PDBSession, + IPDBRawSymbol &RawSymbol) { + std::unique_ptr S = create(PDBSession, RawSymbol); + return unique_dyn_cast_or_null(std::move(S)); + } virtual ~PDBSymbol(); @@ -80,7 +112,8 @@ public: /// normally goes on the right side of the symbol. virtual void dumpRight(PDBSymDumper &Dumper) const {} - void defaultDump(raw_ostream &OS, int Indent) const; + void defaultDump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowFlags, + PdbSymbolIdField RecurseFlags) const; void dumpProperties() const; void dumpChildStats() const; @@ -94,8 +127,6 @@ public: return Enumerator->getNext(); } - std::unique_ptr clone() const; - template std::unique_ptr> findAllChildren() const { auto BaseIter = RawSymbol->findChildren(T::Tag); @@ -131,7 +162,8 @@ protected: } const IPDBSession &Session; - std::unique_ptr RawSymbol; + std::unique_ptr OwnedRawSymbol; + IPDBRawSymbol *RawSymbol = nullptr; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h index 3169146e5b1..ef00df15cb0 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h @@ -18,12 +18,9 @@ class raw_ostream; namespace pdb { class PDBSymbolAnnotation : public PDBSymbol { -public: - PDBSymbolAnnotation(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Annotation) +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAddressOffset) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h index d81da1eaa02..2cf9c72a888 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolBlock : public PDBSymbol { -public: - PDBSymbolBlock(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Block) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAddressOffset) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h index 9549089c7eb..04dbd962ebd 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h @@ -20,12 +20,8 @@ class raw_ostream; namespace pdb { class PDBSymbolCompiland : public PDBSymbol { -public: - PDBSymbolCompiland(const IPDBSession &PDBSession, - std::unique_ptr CompilandSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Compiland) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h index dba50c42cf8..3d651a464d9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolCompilandDetails : public PDBSymbol { -public: - PDBSymbolCompilandDetails(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandDetails) - +public: void dump(PDBSymDumper &Dumper) const override; void getFrontEndVersion(VersionInfo &Version) const { diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h index 7868f045908..ffc408314d9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h @@ -18,12 +18,8 @@ namespace llvm { class raw_ostream; namespace pdb { class PDBSymbolCompilandEnv : public PDBSymbol { -public: - PDBSymbolCompilandEnv(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandEnv) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_ID_METHOD(getLexicalParent) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h index 54f08940426..c29e4c31d3f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h @@ -23,12 +23,8 @@ namespace pdb { /// fit anywhere else in the lexical hierarchy. /// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx class PDBSymbolCustom : public PDBSymbol { -public: - PDBSymbolCustom(const IPDBSession &PDBSession, - std::unique_ptr CustomSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom) - +public: void dump(PDBSymDumper &Dumper) const override; void getDataBytes(llvm::SmallVector &bytes); diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h index 76b14bf1778..217e1e976e6 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -21,12 +21,8 @@ class raw_ostream; namespace pdb { class PDBSymbolData : public PDBSymbol { -public: - PDBSymbolData(const IPDBSession &PDBSession, - std::unique_ptr DataSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAccess) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h index 2c2d7466504..366d0cf4777 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h @@ -20,12 +20,8 @@ class raw_ostream; namespace pdb { class PDBSymbolExe : public PDBSymbol { -public: - PDBSymbolExe(const IPDBSession &PDBSession, - std::unique_ptr ExeSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Exe) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAge) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h index 05d585d2576..129e557c7f2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -22,18 +22,14 @@ class raw_ostream; namespace pdb { class PDBSymbolFunc : public PDBSymbol { + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) public: - PDBSymbolFunc(const IPDBSession &PDBSession, - std::unique_ptr FuncSymbol); - void dump(PDBSymDumper &Dumper) const override; bool isDestructor() const; std::unique_ptr> getArguments() const; - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) - FORWARD_SYMBOL_METHOD(getAccess) FORWARD_SYMBOL_METHOD(getAddressOffset) FORWARD_SYMBOL_METHOD(getAddressSection) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h index 3341bd9b30f..18db8a50fd1 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h @@ -20,12 +20,8 @@ class raw_ostream; namespace pdb { class PDBSymbolFuncDebugEnd : public PDBSymbol { -public: - PDBSymbolFuncDebugEnd(const IPDBSession &PDBSession, - std::unique_ptr FuncDebugEndSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugEnd) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAddressOffset) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h index 6729838597c..83d82f0cbcc 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolFuncDebugStart : public PDBSymbol { -public: - PDBSymbolFuncDebugStart(const IPDBSession &PDBSession, - std::unique_ptr FuncDebugStartSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugStart) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAddressOffset) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h index c2b1c28c929..8b2617fcd75 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolLabel : public PDBSymbol { -public: - PDBSymbolLabel(const IPDBSession &PDBSession, - std::unique_ptr LabelSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Label) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAddressOffset) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h index c9e6ee67c57..9def3edb469 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolPublicSymbol : public PDBSymbol { -public: - PDBSymbolPublicSymbol(const IPDBSession &PDBSession, - std::unique_ptr PublicSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PublicSymbol) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAddressOffset) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h index 614fad86caa..7bb0555362d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolThunk : public PDBSymbol { -public: - PDBSymbolThunk(const IPDBSession &PDBSession, - std::unique_ptr ThunkSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Thunk) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAccess) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h index 39b7d3b300e..488f668bdc1 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeArray : public PDBSymbol { -public: - PDBSymbolTypeArray(const IPDBSession &PDBSession, - std::unique_ptr ArrayTypeSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType) - +public: void dump(PDBSymDumper &Dumper) const override; void dumpRight(PDBSymDumper &Dumper) const override; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h index d607a3d8117..550deedd750 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -22,12 +22,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeBaseClass : public PDBSymbol { -public: - PDBSymbolTypeBaseClass(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BaseClass) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getAccess) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h index 5b1863c42a0..e07e88802b8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeBuiltin : public PDBSymbol { -public: - PDBSymbolTypeBuiltin(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getBuiltinType) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h index 199b3f8b304..0d8979c9c5c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeCustom : public PDBSymbol { -public: - PDBSymbolTypeCustom(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CustomType) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getOemId) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h index e635eb5bbf6..58292a63501 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeDimension : public PDBSymbol { -public: - PDBSymbolTypeDimension(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Dimension) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getLowerBoundId) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h index ddbe7e58f18..f463047bb5b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -21,12 +21,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeEnum : public PDBSymbol { -public: - PDBSymbolTypeEnum(const IPDBSession &PDBSession, - std::unique_ptr EnumTypeSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Enum) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getBuiltinType) @@ -38,6 +34,7 @@ public: FORWARD_SYMBOL_METHOD(hasNestedTypes) FORWARD_SYMBOL_METHOD(getLength) FORWARD_SYMBOL_ID_METHOD(getLexicalParent) + FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType) FORWARD_SYMBOL_METHOD(getName) FORWARD_SYMBOL_METHOD(getSrcLineOnTypeDefn) FORWARD_SYMBOL_METHOD(isNested) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h index 24c13128111..5b940b0737a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeFriend : public PDBSymbol { -public: - PDBSymbolTypeFriend(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Friend) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_ID_METHOD(getClassParent) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h index 3855999c473..074cb418fc8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeFunctionArg : public PDBSymbol { -public: - PDBSymbolTypeFunctionArg(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionArg) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_ID_METHOD(getClassParent) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h index abd4cf5effa..dfdf436197c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeFunctionSig : public PDBSymbol { -public: - PDBSymbolTypeFunctionSig(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig) - +public: std::unique_ptr getArguments() const; void dump(PDBSymDumper &Dumper) const override; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h index 31cf5363dde..d716abd640c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeManaged : public PDBSymbol { -public: - PDBSymbolTypeManaged(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ManagedType) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getName) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h index 7612ebac31d..300d6722fc4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -19,16 +19,13 @@ class raw_ostream; namespace pdb { class PDBSymbolTypePointer : public PDBSymbol { -public: - PDBSymbolTypePointer(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType) - +public: void dump(PDBSymDumper &Dumper) const override; void dumpRight(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_ID_METHOD(getClassParent) FORWARD_SYMBOL_METHOD(getLength) FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_METHOD(isReference) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h index 16c1d1b88c6..d6e2a36486d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeTypedef : public PDBSymbol { -public: - PDBSymbolTypeTypedef(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Typedef) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getBuiltinType) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h index e259b6dca3d..937dd6c8722 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -23,17 +23,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeUDT : public PDBSymbol { -public: - PDBSymbolTypeUDT(const IPDBSession &PDBSession, - std::unique_ptr UDTSymbol); - - std::unique_ptr clone() const { - return getSession().getConcreteSymbolById( - getSymIndexId()); - } - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_ID_METHOD(getClassParent) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h index e270c2b7eb9..6efce4bbd68 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeVTable : public PDBSymbol { -public: - PDBSymbolTypeVTable(const IPDBSession &PDBSession, - std::unique_ptr VtblSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTable) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_ID_METHOD(getClassParent) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h index 8acaabea5bb..8949052b0c0 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h @@ -19,12 +19,8 @@ class raw_ostream; namespace pdb { class PDBSymbolTypeVTableShape : public PDBSymbol { -public: - PDBSymbolTypeVTableShape(const IPDBSession &PDBSession, - std::unique_ptr VtblShapeSymbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTableShape) - +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(isConstType) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h index de43e47badb..e935ac6ce0d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h @@ -18,16 +18,11 @@ class raw_ostream; namespace pdb { class PDBSymbolUnknown : public PDBSymbol { + DECLARE_PDB_SYMBOL_CUSTOM_TYPE(S->getSymTag() == PDB_SymType::None || + S->getSymTag() >= PDB_SymType::Max) + public: - PDBSymbolUnknown(const IPDBSession &PDBSession, - std::unique_ptr UnknownSymbol); - void dump(PDBSymDumper &Dumper) const override; - - static bool classof(const PDBSymbol *S) { - return (S->getSymTag() == PDB_SymType::None || - S->getSymTag() >= PDB_SymType::Max); - } }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h index 70fbd5b84c3..4e8c99fc8d8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h @@ -19,12 +19,9 @@ class raw_ostream; namespace pdb { class PDBSymbolUsingNamespace : public PDBSymbol { -public: - PDBSymbolUsingNamespace(const IPDBSession &PDBSession, - std::unique_ptr Symbol); - DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UsingNamespace) +public: void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_ID_METHOD(getLexicalParent) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h index da6cb1d2677..917f3ed7391 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -12,6 +12,7 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBFrameData.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include #include @@ -22,6 +23,8 @@ namespace llvm { namespace pdb { +typedef uint32_t SymIndexId; + class IPDBDataStream; class IPDBInjectedSource; class IPDBLineNumber; @@ -69,6 +72,7 @@ using IPDBEnumLineNumbers = IPDBEnumChildren; using IPDBEnumTables = IPDBEnumChildren; using IPDBEnumInjectedSources = IPDBEnumChildren; using IPDBEnumSectionContribs = IPDBEnumChildren; +using IPDBEnumFrameData = IPDBEnumChildren; /// Specifies which PDB reader implementation is to be used. Only a value /// of PDB_ReaderType::DIA is currently supported, but Native is in the works. @@ -208,6 +212,18 @@ enum class PDB_SymType { CustomType, ManagedType, Dimension, + CallSite, + InlineSite, + BaseInterface, + VectorType, + MatrixType, + HLSLType, + Caller, + Callee, + Export, + HeapAllocationSite, + CoffGroup, + Inlinee, Max }; @@ -334,6 +350,36 @@ enum PDB_VariantType { struct Variant { Variant() = default; + explicit Variant(bool V) : Type(PDB_VariantType::Bool) { Value.Bool = V; } + explicit Variant(int8_t V) : Type(PDB_VariantType::Int8) { Value.Int8 = V; } + explicit Variant(int16_t V) : Type(PDB_VariantType::Int16) { + Value.Int16 = V; + } + explicit Variant(int32_t V) : Type(PDB_VariantType::Int32) { + Value.Int32 = V; + } + explicit Variant(int64_t V) : Type(PDB_VariantType::Int64) { + Value.Int64 = V; + } + explicit Variant(float V) : Type(PDB_VariantType::Single) { + Value.Single = V; + } + explicit Variant(double V) : Type(PDB_VariantType::Double) { + Value.Double = V; + } + explicit Variant(uint8_t V) : Type(PDB_VariantType::UInt8) { + Value.UInt8 = V; + } + explicit Variant(uint16_t V) : Type(PDB_VariantType::UInt16) { + Value.UInt16 = V; + } + explicit Variant(uint32_t V) : Type(PDB_VariantType::UInt32) { + Value.UInt32 = V; + } + explicit Variant(uint64_t V) : Type(PDB_VariantType::UInt64) { + Value.UInt64 = V; + } + Variant(const Variant &Other) { *this = Other; } diff --git a/contrib/llvm/lib/Demangle/Compiler.h b/contrib/llvm/include/llvm/Demangle/Compiler.h similarity index 100% rename from contrib/llvm/lib/Demangle/Compiler.h rename to contrib/llvm/include/llvm/Demangle/Compiler.h diff --git a/contrib/llvm/include/llvm/Demangle/Demangle.h b/contrib/llvm/include/llvm/Demangle/Demangle.h index df7753f23b8..4c9dc9569e1 100644 --- a/contrib/llvm/include/llvm/Demangle/Demangle.h +++ b/contrib/llvm/include/llvm/Demangle/Demangle.h @@ -7,6 +7,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_DEMANGLE_DEMANGLE_H +#define LLVM_DEMANGLE_DEMANGLE_H + #include namespace llvm { @@ -27,8 +30,11 @@ enum : int { char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n, int *status); + + +enum MSDemangleFlags { MSDF_None = 0, MSDF_DumpBackrefs = 1 << 0 }; char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n, - int *status); + int *status, MSDemangleFlags Flags = MSDF_None); /// "Partial" demangler. This supports demangling a string into an AST /// (typically an intermediate stage in itaniumDemangle) and querying certain @@ -86,3 +92,5 @@ private: void *Context; }; } // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Demangle/ItaniumDemangle.h b/contrib/llvm/include/llvm/Demangle/ItaniumDemangle.h new file mode 100644 index 00000000000..0b9187f30a5 --- /dev/null +++ b/contrib/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -0,0 +1,5184 @@ +//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEMANGLE_ITANIUMDEMANGLE_H +#define LLVM_DEMANGLE_ITANIUMDEMANGLE_H + +// FIXME: (possibly) incomplete list of features that clang mangles that this +// file does not yet support: +// - C++ modules TS + +#include "llvm/Demangle/Compiler.h" +#include "llvm/Demangle/StringView.h" +#include "llvm/Demangle/Utility.h" + +#include +#include +#include +#include +#include +#include +#include + +#define FOR_EACH_NODE_KIND(X) \ + X(NodeArrayNode) \ + X(DotSuffix) \ + X(VendorExtQualType) \ + X(QualType) \ + X(ConversionOperatorType) \ + X(PostfixQualifiedType) \ + X(ElaboratedTypeSpefType) \ + X(NameType) \ + X(AbiTagAttr) \ + X(EnableIfAttr) \ + X(ObjCProtoName) \ + X(PointerType) \ + X(ReferenceType) \ + X(PointerToMemberType) \ + X(ArrayType) \ + X(FunctionType) \ + X(NoexceptSpec) \ + X(DynamicExceptionSpec) \ + X(FunctionEncoding) \ + X(LiteralOperator) \ + X(SpecialName) \ + X(CtorVtableSpecialName) \ + X(QualifiedName) \ + X(NestedName) \ + X(LocalName) \ + X(VectorType) \ + X(PixelVectorType) \ + X(ParameterPack) \ + X(TemplateArgumentPack) \ + X(ParameterPackExpansion) \ + X(TemplateArgs) \ + X(ForwardTemplateReference) \ + X(NameWithTemplateArgs) \ + X(GlobalQualifiedName) \ + X(StdQualifiedName) \ + X(ExpandedSpecialSubstitution) \ + X(SpecialSubstitution) \ + X(CtorDtorName) \ + X(DtorName) \ + X(UnnamedTypeName) \ + X(ClosureTypeName) \ + X(StructuredBindingName) \ + X(BinaryExpr) \ + X(ArraySubscriptExpr) \ + X(PostfixExpr) \ + X(ConditionalExpr) \ + X(MemberExpr) \ + X(EnclosingExpr) \ + X(CastExpr) \ + X(SizeofParamPackExpr) \ + X(CallExpr) \ + X(NewExpr) \ + X(DeleteExpr) \ + X(PrefixExpr) \ + X(FunctionParam) \ + X(ConversionExpr) \ + X(InitListExpr) \ + X(FoldExpr) \ + X(ThrowExpr) \ + X(BoolExpr) \ + X(IntegerCastExpr) \ + X(IntegerLiteral) \ + X(FloatLiteral) \ + X(DoubleLiteral) \ + X(LongDoubleLiteral) \ + X(BracedExpr) \ + X(BracedRangeExpr) + +namespace llvm { +namespace itanium_demangle { +// Base class of all AST nodes. The AST is built by the parser, then is +// traversed by the printLeft/Right functions to produce a demangled string. +class Node { +public: + enum Kind : unsigned char { +#define ENUMERATOR(NodeKind) K ## NodeKind, + FOR_EACH_NODE_KIND(ENUMERATOR) +#undef ENUMERATOR + }; + + /// Three-way bool to track a cached value. Unknown is possible if this node + /// has an unexpanded parameter pack below it that may affect this cache. + enum class Cache : unsigned char { Yes, No, Unknown, }; + +private: + Kind K; + + // FIXME: Make these protected. +public: + /// Tracks if this node has a component on its right side, in which case we + /// need to call printRight. + Cache RHSComponentCache; + + /// Track if this node is a (possibly qualified) array type. This can affect + /// how we format the output string. + Cache ArrayCache; + + /// Track if this node is a (possibly qualified) function type. This can + /// affect how we format the output string. + Cache FunctionCache; + +public: + Node(Kind K_, Cache RHSComponentCache_ = Cache::No, + Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No) + : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_), + FunctionCache(FunctionCache_) {} + + /// Visit the most-derived object corresponding to this object. + template void visit(Fn F) const; + + // The following function is provided by all derived classes: + // + // Call F with arguments that, when passed to the constructor of this node, + // would construct an equivalent node. + //template void match(Fn F) const; + + bool hasRHSComponent(OutputStream &S) const { + if (RHSComponentCache != Cache::Unknown) + return RHSComponentCache == Cache::Yes; + return hasRHSComponentSlow(S); + } + + bool hasArray(OutputStream &S) const { + if (ArrayCache != Cache::Unknown) + return ArrayCache == Cache::Yes; + return hasArraySlow(S); + } + + bool hasFunction(OutputStream &S) const { + if (FunctionCache != Cache::Unknown) + return FunctionCache == Cache::Yes; + return hasFunctionSlow(S); + } + + Kind getKind() const { return K; } + + virtual bool hasRHSComponentSlow(OutputStream &) const { return false; } + virtual bool hasArraySlow(OutputStream &) const { return false; } + virtual bool hasFunctionSlow(OutputStream &) const { return false; } + + // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to + // get at a node that actually represents some concrete syntax. + virtual const Node *getSyntaxNode(OutputStream &) const { + return this; + } + + void print(OutputStream &S) const { + printLeft(S); + if (RHSComponentCache != Cache::No) + printRight(S); + } + + // Print the "left" side of this Node into OutputStream. + virtual void printLeft(OutputStream &) const = 0; + + // Print the "right". This distinction is necessary to represent C++ types + // that appear on the RHS of their subtype, such as arrays or functions. + // Since most types don't have such a component, provide a default + // implementation. + virtual void printRight(OutputStream &) const {} + + virtual StringView getBaseName() const { return StringView(); } + + // Silence compiler warnings, this dtor will never be called. + virtual ~Node() = default; + +#ifndef NDEBUG + LLVM_DUMP_METHOD void dump() const; +#endif +}; + +class NodeArray { + Node **Elements; + size_t NumElements; + +public: + NodeArray() : Elements(nullptr), NumElements(0) {} + NodeArray(Node **Elements_, size_t NumElements_) + : Elements(Elements_), NumElements(NumElements_) {} + + bool empty() const { return NumElements == 0; } + size_t size() const { return NumElements; } + + Node **begin() const { return Elements; } + Node **end() const { return Elements + NumElements; } + + Node *operator[](size_t Idx) const { return Elements[Idx]; } + + void printWithComma(OutputStream &S) const { + bool FirstElement = true; + for (size_t Idx = 0; Idx != NumElements; ++Idx) { + size_t BeforeComma = S.getCurrentPosition(); + if (!FirstElement) + S += ", "; + size_t AfterComma = S.getCurrentPosition(); + Elements[Idx]->print(S); + + // Elements[Idx] is an empty parameter pack expansion, we should erase the + // comma we just printed. + if (AfterComma == S.getCurrentPosition()) { + S.setCurrentPosition(BeforeComma); + continue; + } + + FirstElement = false; + } + } +}; + +struct NodeArrayNode : Node { + NodeArray Array; + NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {} + + template void match(Fn F) const { F(Array); } + + void printLeft(OutputStream &S) const override { + Array.printWithComma(S); + } +}; + +class DotSuffix final : public Node { + const Node *Prefix; + const StringView Suffix; + +public: + DotSuffix(const Node *Prefix_, StringView Suffix_) + : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {} + + template void match(Fn F) const { F(Prefix, Suffix); } + + void printLeft(OutputStream &s) const override { + Prefix->print(s); + s += " ("; + s += Suffix; + s += ")"; + } +}; + +class VendorExtQualType final : public Node { + const Node *Ty; + StringView Ext; + +public: + VendorExtQualType(const Node *Ty_, StringView Ext_) + : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {} + + template void match(Fn F) const { F(Ty, Ext); } + + void printLeft(OutputStream &S) const override { + Ty->print(S); + S += " "; + S += Ext; + } +}; + +enum FunctionRefQual : unsigned char { + FrefQualNone, + FrefQualLValue, + FrefQualRValue, +}; + +enum Qualifiers { + QualNone = 0, + QualConst = 0x1, + QualVolatile = 0x2, + QualRestrict = 0x4, +}; + +inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) { + return Q1 = static_cast(Q1 | Q2); +} + +class QualType : public Node { +protected: + const Qualifiers Quals; + const Node *Child; + + void printQuals(OutputStream &S) const { + if (Quals & QualConst) + S += " const"; + if (Quals & QualVolatile) + S += " volatile"; + if (Quals & QualRestrict) + S += " restrict"; + } + +public: + QualType(const Node *Child_, Qualifiers Quals_) + : Node(KQualType, Child_->RHSComponentCache, + Child_->ArrayCache, Child_->FunctionCache), + Quals(Quals_), Child(Child_) {} + + template void match(Fn F) const { F(Child, Quals); } + + bool hasRHSComponentSlow(OutputStream &S) const override { + return Child->hasRHSComponent(S); + } + bool hasArraySlow(OutputStream &S) const override { + return Child->hasArray(S); + } + bool hasFunctionSlow(OutputStream &S) const override { + return Child->hasFunction(S); + } + + void printLeft(OutputStream &S) const override { + Child->printLeft(S); + printQuals(S); + } + + void printRight(OutputStream &S) const override { Child->printRight(S); } +}; + +class ConversionOperatorType final : public Node { + const Node *Ty; + +public: + ConversionOperatorType(const Node *Ty_) + : Node(KConversionOperatorType), Ty(Ty_) {} + + template void match(Fn F) const { F(Ty); } + + void printLeft(OutputStream &S) const override { + S += "operator "; + Ty->print(S); + } +}; + +class PostfixQualifiedType final : public Node { + const Node *Ty; + const StringView Postfix; + +public: + PostfixQualifiedType(Node *Ty_, StringView Postfix_) + : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {} + + template void match(Fn F) const { F(Ty, Postfix); } + + void printLeft(OutputStream &s) const override { + Ty->printLeft(s); + s += Postfix; + } +}; + +class NameType final : public Node { + const StringView Name; + +public: + NameType(StringView Name_) : Node(KNameType), Name(Name_) {} + + template void match(Fn F) const { F(Name); } + + StringView getName() const { return Name; } + StringView getBaseName() const override { return Name; } + + void printLeft(OutputStream &s) const override { s += Name; } +}; + +class ElaboratedTypeSpefType : public Node { + StringView Kind; + Node *Child; +public: + ElaboratedTypeSpefType(StringView Kind_, Node *Child_) + : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {} + + template void match(Fn F) const { F(Kind, Child); } + + void printLeft(OutputStream &S) const override { + S += Kind; + S += ' '; + Child->print(S); + } +}; + +struct AbiTagAttr : Node { + Node *Base; + StringView Tag; + + AbiTagAttr(Node* Base_, StringView Tag_) + : Node(KAbiTagAttr, Base_->RHSComponentCache, + Base_->ArrayCache, Base_->FunctionCache), + Base(Base_), Tag(Tag_) {} + + template void match(Fn F) const { F(Base, Tag); } + + void printLeft(OutputStream &S) const override { + Base->printLeft(S); + S += "[abi:"; + S += Tag; + S += "]"; + } +}; + +class EnableIfAttr : public Node { + NodeArray Conditions; +public: + EnableIfAttr(NodeArray Conditions_) + : Node(KEnableIfAttr), Conditions(Conditions_) {} + + template void match(Fn F) const { F(Conditions); } + + void printLeft(OutputStream &S) const override { + S += " [enable_if:"; + Conditions.printWithComma(S); + S += ']'; + } +}; + +class ObjCProtoName : public Node { + const Node *Ty; + StringView Protocol; + + friend class PointerType; + +public: + ObjCProtoName(const Node *Ty_, StringView Protocol_) + : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {} + + template void match(Fn F) const { F(Ty, Protocol); } + + bool isObjCObject() const { + return Ty->getKind() == KNameType && + static_cast(Ty)->getName() == "objc_object"; + } + + void printLeft(OutputStream &S) const override { + Ty->print(S); + S += "<"; + S += Protocol; + S += ">"; + } +}; + +class PointerType final : public Node { + const Node *Pointee; + +public: + PointerType(const Node *Pointee_) + : Node(KPointerType, Pointee_->RHSComponentCache), + Pointee(Pointee_) {} + + template void match(Fn F) const { F(Pointee); } + + bool hasRHSComponentSlow(OutputStream &S) const override { + return Pointee->hasRHSComponent(S); + } + + void printLeft(OutputStream &s) const override { + // We rewrite objc_object* into id. + if (Pointee->getKind() != KObjCProtoName || + !static_cast(Pointee)->isObjCObject()) { + Pointee->printLeft(s); + if (Pointee->hasArray(s)) + s += " "; + if (Pointee->hasArray(s) || Pointee->hasFunction(s)) + s += "("; + s += "*"; + } else { + const auto *objcProto = static_cast(Pointee); + s += "id<"; + s += objcProto->Protocol; + s += ">"; + } + } + + void printRight(OutputStream &s) const override { + if (Pointee->getKind() != KObjCProtoName || + !static_cast(Pointee)->isObjCObject()) { + if (Pointee->hasArray(s) || Pointee->hasFunction(s)) + s += ")"; + Pointee->printRight(s); + } + } +}; + +enum class ReferenceKind { + LValue, + RValue, +}; + +// Represents either a LValue or an RValue reference type. +class ReferenceType : public Node { + const Node *Pointee; + ReferenceKind RK; + + mutable bool Printing = false; + + // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The + // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any + // other combination collapses to a lvalue ref. + std::pair collapse(OutputStream &S) const { + auto SoFar = std::make_pair(RK, Pointee); + for (;;) { + const Node *SN = SoFar.second->getSyntaxNode(S); + if (SN->getKind() != KReferenceType) + break; + auto *RT = static_cast(SN); + SoFar.second = RT->Pointee; + SoFar.first = std::min(SoFar.first, RT->RK); + } + return SoFar; + } + +public: + ReferenceType(const Node *Pointee_, ReferenceKind RK_) + : Node(KReferenceType, Pointee_->RHSComponentCache), + Pointee(Pointee_), RK(RK_) {} + + template void match(Fn F) const { F(Pointee, RK); } + + bool hasRHSComponentSlow(OutputStream &S) const override { + return Pointee->hasRHSComponent(S); + } + + void printLeft(OutputStream &s) const override { + if (Printing) + return; + SwapAndRestore SavePrinting(Printing, true); + std::pair Collapsed = collapse(s); + Collapsed.second->printLeft(s); + if (Collapsed.second->hasArray(s)) + s += " "; + if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) + s += "("; + + s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&"); + } + void printRight(OutputStream &s) const override { + if (Printing) + return; + SwapAndRestore SavePrinting(Printing, true); + std::pair Collapsed = collapse(s); + if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) + s += ")"; + Collapsed.second->printRight(s); + } +}; + +class PointerToMemberType final : public Node { + const Node *ClassType; + const Node *MemberType; + +public: + PointerToMemberType(const Node *ClassType_, const Node *MemberType_) + : Node(KPointerToMemberType, MemberType_->RHSComponentCache), + ClassType(ClassType_), MemberType(MemberType_) {} + + template void match(Fn F) const { F(ClassType, MemberType); } + + bool hasRHSComponentSlow(OutputStream &S) const override { + return MemberType->hasRHSComponent(S); + } + + void printLeft(OutputStream &s) const override { + MemberType->printLeft(s); + if (MemberType->hasArray(s) || MemberType->hasFunction(s)) + s += "("; + else + s += " "; + ClassType->print(s); + s += "::*"; + } + + void printRight(OutputStream &s) const override { + if (MemberType->hasArray(s) || MemberType->hasFunction(s)) + s += ")"; + MemberType->printRight(s); + } +}; + +class NodeOrString { + const void *First; + const void *Second; + +public: + /* implicit */ NodeOrString(StringView Str) { + const char *FirstChar = Str.begin(); + const char *SecondChar = Str.end(); + if (SecondChar == nullptr) { + assert(FirstChar == SecondChar); + ++FirstChar, ++SecondChar; + } + First = static_cast(FirstChar); + Second = static_cast(SecondChar); + } + + /* implicit */ NodeOrString(Node *N) + : First(static_cast(N)), Second(nullptr) {} + NodeOrString() : First(nullptr), Second(nullptr) {} + + bool isString() const { return Second && First; } + bool isNode() const { return First && !Second; } + bool isEmpty() const { return !First && !Second; } + + StringView asString() const { + assert(isString()); + return StringView(static_cast(First), + static_cast(Second)); + } + + const Node *asNode() const { + assert(isNode()); + return static_cast(First); + } +}; + +class ArrayType final : public Node { + const Node *Base; + NodeOrString Dimension; + +public: + ArrayType(const Node *Base_, NodeOrString Dimension_) + : Node(KArrayType, + /*RHSComponentCache=*/Cache::Yes, + /*ArrayCache=*/Cache::Yes), + Base(Base_), Dimension(Dimension_) {} + + template void match(Fn F) const { F(Base, Dimension); } + + bool hasRHSComponentSlow(OutputStream &) const override { return true; } + bool hasArraySlow(OutputStream &) const override { return true; } + + void printLeft(OutputStream &S) const override { Base->printLeft(S); } + + void printRight(OutputStream &S) const override { + if (S.back() != ']') + S += " "; + S += "["; + if (Dimension.isString()) + S += Dimension.asString(); + else if (Dimension.isNode()) + Dimension.asNode()->print(S); + S += "]"; + Base->printRight(S); + } +}; + +class FunctionType final : public Node { + const Node *Ret; + NodeArray Params; + Qualifiers CVQuals; + FunctionRefQual RefQual; + const Node *ExceptionSpec; + +public: + FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, + FunctionRefQual RefQual_, const Node *ExceptionSpec_) + : Node(KFunctionType, + /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, + /*FunctionCache=*/Cache::Yes), + Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_), + ExceptionSpec(ExceptionSpec_) {} + + template void match(Fn F) const { + F(Ret, Params, CVQuals, RefQual, ExceptionSpec); + } + + bool hasRHSComponentSlow(OutputStream &) const override { return true; } + bool hasFunctionSlow(OutputStream &) const override { return true; } + + // Handle C++'s ... quirky decl grammar by using the left & right + // distinction. Consider: + // int (*f(float))(char) {} + // f is a function that takes a float and returns a pointer to a function + // that takes a char and returns an int. If we're trying to print f, start + // by printing out the return types's left, then print our parameters, then + // finally print right of the return type. + void printLeft(OutputStream &S) const override { + Ret->printLeft(S); + S += " "; + } + + void printRight(OutputStream &S) const override { + S += "("; + Params.printWithComma(S); + S += ")"; + Ret->printRight(S); + + if (CVQuals & QualConst) + S += " const"; + if (CVQuals & QualVolatile) + S += " volatile"; + if (CVQuals & QualRestrict) + S += " restrict"; + + if (RefQual == FrefQualLValue) + S += " &"; + else if (RefQual == FrefQualRValue) + S += " &&"; + + if (ExceptionSpec != nullptr) { + S += ' '; + ExceptionSpec->print(S); + } + } +}; + +class NoexceptSpec : public Node { + const Node *E; +public: + NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {} + + template void match(Fn F) const { F(E); } + + void printLeft(OutputStream &S) const override { + S += "noexcept("; + E->print(S); + S += ")"; + } +}; + +class DynamicExceptionSpec : public Node { + NodeArray Types; +public: + DynamicExceptionSpec(NodeArray Types_) + : Node(KDynamicExceptionSpec), Types(Types_) {} + + template void match(Fn F) const { F(Types); } + + void printLeft(OutputStream &S) const override { + S += "throw("; + Types.printWithComma(S); + S += ')'; + } +}; + +class FunctionEncoding final : public Node { + const Node *Ret; + const Node *Name; + NodeArray Params; + const Node *Attrs; + Qualifiers CVQuals; + FunctionRefQual RefQual; + +public: + FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_, + const Node *Attrs_, Qualifiers CVQuals_, + FunctionRefQual RefQual_) + : Node(KFunctionEncoding, + /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, + /*FunctionCache=*/Cache::Yes), + Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_), + CVQuals(CVQuals_), RefQual(RefQual_) {} + + template void match(Fn F) const { + F(Ret, Name, Params, Attrs, CVQuals, RefQual); + } + + Qualifiers getCVQuals() const { return CVQuals; } + FunctionRefQual getRefQual() const { return RefQual; } + NodeArray getParams() const { return Params; } + const Node *getReturnType() const { return Ret; } + + bool hasRHSComponentSlow(OutputStream &) const override { return true; } + bool hasFunctionSlow(OutputStream &) const override { return true; } + + const Node *getName() const { return Name; } + + void printLeft(OutputStream &S) const override { + if (Ret) { + Ret->printLeft(S); + if (!Ret->hasRHSComponent(S)) + S += " "; + } + Name->print(S); + } + + void printRight(OutputStream &S) const override { + S += "("; + Params.printWithComma(S); + S += ")"; + if (Ret) + Ret->printRight(S); + + if (CVQuals & QualConst) + S += " const"; + if (CVQuals & QualVolatile) + S += " volatile"; + if (CVQuals & QualRestrict) + S += " restrict"; + + if (RefQual == FrefQualLValue) + S += " &"; + else if (RefQual == FrefQualRValue) + S += " &&"; + + if (Attrs != nullptr) + Attrs->print(S); + } +}; + +class LiteralOperator : public Node { + const Node *OpName; + +public: + LiteralOperator(const Node *OpName_) + : Node(KLiteralOperator), OpName(OpName_) {} + + template void match(Fn F) const { F(OpName); } + + void printLeft(OutputStream &S) const override { + S += "operator\"\" "; + OpName->print(S); + } +}; + +class SpecialName final : public Node { + const StringView Special; + const Node *Child; + +public: + SpecialName(StringView Special_, const Node *Child_) + : Node(KSpecialName), Special(Special_), Child(Child_) {} + + template void match(Fn F) const { F(Special, Child); } + + void printLeft(OutputStream &S) const override { + S += Special; + Child->print(S); + } +}; + +class CtorVtableSpecialName final : public Node { + const Node *FirstType; + const Node *SecondType; + +public: + CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_) + : Node(KCtorVtableSpecialName), + FirstType(FirstType_), SecondType(SecondType_) {} + + template void match(Fn F) const { F(FirstType, SecondType); } + + void printLeft(OutputStream &S) const override { + S += "construction vtable for "; + FirstType->print(S); + S += "-in-"; + SecondType->print(S); + } +}; + +struct NestedName : Node { + Node *Qual; + Node *Name; + + NestedName(Node *Qual_, Node *Name_) + : Node(KNestedName), Qual(Qual_), Name(Name_) {} + + template void match(Fn F) const { F(Qual, Name); } + + StringView getBaseName() const override { return Name->getBaseName(); } + + void printLeft(OutputStream &S) const override { + Qual->print(S); + S += "::"; + Name->print(S); + } +}; + +struct LocalName : Node { + Node *Encoding; + Node *Entity; + + LocalName(Node *Encoding_, Node *Entity_) + : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {} + + template void match(Fn F) const { F(Encoding, Entity); } + + void printLeft(OutputStream &S) const override { + Encoding->print(S); + S += "::"; + Entity->print(S); + } +}; + +class QualifiedName final : public Node { + // qualifier::name + const Node *Qualifier; + const Node *Name; + +public: + QualifiedName(const Node *Qualifier_, const Node *Name_) + : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {} + + template void match(Fn F) const { F(Qualifier, Name); } + + StringView getBaseName() const override { return Name->getBaseName(); } + + void printLeft(OutputStream &S) const override { + Qualifier->print(S); + S += "::"; + Name->print(S); + } +}; + +class VectorType final : public Node { + const Node *BaseType; + const NodeOrString Dimension; + +public: + VectorType(const Node *BaseType_, NodeOrString Dimension_) + : Node(KVectorType), BaseType(BaseType_), + Dimension(Dimension_) {} + + template void match(Fn F) const { F(BaseType, Dimension); } + + void printLeft(OutputStream &S) const override { + BaseType->print(S); + S += " vector["; + if (Dimension.isNode()) + Dimension.asNode()->print(S); + else if (Dimension.isString()) + S += Dimension.asString(); + S += "]"; + } +}; + +class PixelVectorType final : public Node { + const NodeOrString Dimension; + +public: + PixelVectorType(NodeOrString Dimension_) + : Node(KPixelVectorType), Dimension(Dimension_) {} + + template void match(Fn F) const { F(Dimension); } + + void printLeft(OutputStream &S) const override { + // FIXME: This should demangle as "vector pixel". + S += "pixel vector["; + S += Dimension.asString(); + S += "]"; + } +}; + +/// An unexpanded parameter pack (either in the expression or type context). If +/// this AST is correct, this node will have a ParameterPackExpansion node above +/// it. +/// +/// This node is created when some are found that apply to an +/// , and is stored in the TemplateParams table. In order for this to +/// appear in the final AST, it has to referenced via a (ie, +/// T_). +class ParameterPack final : public Node { + NodeArray Data; + + // Setup OutputStream for a pack expansion unless we're already expanding one. + void initializePackExpansion(OutputStream &S) const { + if (S.CurrentPackMax == std::numeric_limits::max()) { + S.CurrentPackMax = static_cast(Data.size()); + S.CurrentPackIndex = 0; + } + } + +public: + ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) { + ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown; + if (std::all_of(Data.begin(), Data.end(), [](Node* P) { + return P->ArrayCache == Cache::No; + })) + ArrayCache = Cache::No; + if (std::all_of(Data.begin(), Data.end(), [](Node* P) { + return P->FunctionCache == Cache::No; + })) + FunctionCache = Cache::No; + if (std::all_of(Data.begin(), Data.end(), [](Node* P) { + return P->RHSComponentCache == Cache::No; + })) + RHSComponentCache = Cache::No; + } + + template void match(Fn F) const { F(Data); } + + bool hasRHSComponentSlow(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + return Idx < Data.size() && Data[Idx]->hasRHSComponent(S); + } + bool hasArraySlow(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + return Idx < Data.size() && Data[Idx]->hasArray(S); + } + bool hasFunctionSlow(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + return Idx < Data.size() && Data[Idx]->hasFunction(S); + } + const Node *getSyntaxNode(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this; + } + + void printLeft(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + if (Idx < Data.size()) + Data[Idx]->printLeft(S); + } + void printRight(OutputStream &S) const override { + initializePackExpansion(S); + size_t Idx = S.CurrentPackIndex; + if (Idx < Data.size()) + Data[Idx]->printRight(S); + } +}; + +/// A variadic template argument. This node represents an occurrence of +/// JE in some . It isn't itself unexpanded, unless +/// one of it's Elements is. The parser inserts a ParameterPack into the +/// TemplateParams table if the this pack belongs to apply to an +/// . +class TemplateArgumentPack final : public Node { + NodeArray Elements; +public: + TemplateArgumentPack(NodeArray Elements_) + : Node(KTemplateArgumentPack), Elements(Elements_) {} + + template void match(Fn F) const { F(Elements); } + + NodeArray getElements() const { return Elements; } + + void printLeft(OutputStream &S) const override { + Elements.printWithComma(S); + } +}; + +/// A pack expansion. Below this node, there are some unexpanded ParameterPacks +/// which each have Child->ParameterPackSize elements. +class ParameterPackExpansion final : public Node { + const Node *Child; + +public: + ParameterPackExpansion(const Node *Child_) + : Node(KParameterPackExpansion), Child(Child_) {} + + template void match(Fn F) const { F(Child); } + + const Node *getChild() const { return Child; } + + void printLeft(OutputStream &S) const override { + constexpr unsigned Max = std::numeric_limits::max(); + SwapAndRestore SavePackIdx(S.CurrentPackIndex, Max); + SwapAndRestore SavePackMax(S.CurrentPackMax, Max); + size_t StreamPos = S.getCurrentPosition(); + + // Print the first element in the pack. If Child contains a ParameterPack, + // it will set up S.CurrentPackMax and print the first element. + Child->print(S); + + // No ParameterPack was found in Child. This can occur if we've found a pack + // expansion on a . + if (S.CurrentPackMax == Max) { + S += "..."; + return; + } + + // We found a ParameterPack, but it has no elements. Erase whatever we may + // of printed. + if (S.CurrentPackMax == 0) { + S.setCurrentPosition(StreamPos); + return; + } + + // Else, iterate through the rest of the elements in the pack. + for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) { + S += ", "; + S.CurrentPackIndex = I; + Child->print(S); + } + } +}; + +class TemplateArgs final : public Node { + NodeArray Params; + +public: + TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {} + + template void match(Fn F) const { F(Params); } + + NodeArray getParams() { return Params; } + + void printLeft(OutputStream &S) const override { + S += "<"; + Params.printWithComma(S); + if (S.back() == '>') + S += " "; + S += ">"; + } +}; + +/// A forward-reference to a template argument that was not known at the point +/// where the template parameter name was parsed in a mangling. +/// +/// This is created when demangling the name of a specialization of a +/// conversion function template: +/// +/// \code +/// struct A { +/// template operator T*(); +/// }; +/// \endcode +/// +/// When demangling a specialization of the conversion function template, we +/// encounter the name of the template (including the \c T) before we reach +/// the template argument list, so we cannot substitute the parameter name +/// for the corresponding argument while parsing. Instead, we create a +/// \c ForwardTemplateReference node that is resolved after we parse the +/// template arguments. +struct ForwardTemplateReference : Node { + size_t Index; + Node *Ref = nullptr; + + // If we're currently printing this node. It is possible (though invalid) for + // a forward template reference to refer to itself via a substitution. This + // creates a cyclic AST, which will stack overflow printing. To fix this, bail + // out if more than one print* function is active. + mutable bool Printing = false; + + ForwardTemplateReference(size_t Index_) + : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown, + Cache::Unknown), + Index(Index_) {} + + // We don't provide a matcher for these, because the value of the node is + // not determined by its construction parameters, and it generally needs + // special handling. + template void match(Fn F) const = delete; + + bool hasRHSComponentSlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore SavePrinting(Printing, true); + return Ref->hasRHSComponent(S); + } + bool hasArraySlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore SavePrinting(Printing, true); + return Ref->hasArray(S); + } + bool hasFunctionSlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore SavePrinting(Printing, true); + return Ref->hasFunction(S); + } + const Node *getSyntaxNode(OutputStream &S) const override { + if (Printing) + return this; + SwapAndRestore SavePrinting(Printing, true); + return Ref->getSyntaxNode(S); + } + + void printLeft(OutputStream &S) const override { + if (Printing) + return; + SwapAndRestore SavePrinting(Printing, true); + Ref->printLeft(S); + } + void printRight(OutputStream &S) const override { + if (Printing) + return; + SwapAndRestore SavePrinting(Printing, true); + Ref->printRight(S); + } +}; + +struct NameWithTemplateArgs : Node { + // name + Node *Name; + Node *TemplateArgs; + + NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_) + : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {} + + template void match(Fn F) const { F(Name, TemplateArgs); } + + StringView getBaseName() const override { return Name->getBaseName(); } + + void printLeft(OutputStream &S) const override { + Name->print(S); + TemplateArgs->print(S); + } +}; + +class GlobalQualifiedName final : public Node { + Node *Child; + +public: + GlobalQualifiedName(Node* Child_) + : Node(KGlobalQualifiedName), Child(Child_) {} + + template void match(Fn F) const { F(Child); } + + StringView getBaseName() const override { return Child->getBaseName(); } + + void printLeft(OutputStream &S) const override { + S += "::"; + Child->print(S); + } +}; + +struct StdQualifiedName : Node { + Node *Child; + + StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {} + + template void match(Fn F) const { F(Child); } + + StringView getBaseName() const override { return Child->getBaseName(); } + + void printLeft(OutputStream &S) const override { + S += "std::"; + Child->print(S); + } +}; + +enum class SpecialSubKind { + allocator, + basic_string, + string, + istream, + ostream, + iostream, +}; + +class ExpandedSpecialSubstitution final : public Node { + SpecialSubKind SSK; + +public: + ExpandedSpecialSubstitution(SpecialSubKind SSK_) + : Node(KExpandedSpecialSubstitution), SSK(SSK_) {} + + template void match(Fn F) const { F(SSK); } + + StringView getBaseName() const override { + switch (SSK) { + case SpecialSubKind::allocator: + return StringView("allocator"); + case SpecialSubKind::basic_string: + return StringView("basic_string"); + case SpecialSubKind::string: + return StringView("basic_string"); + case SpecialSubKind::istream: + return StringView("basic_istream"); + case SpecialSubKind::ostream: + return StringView("basic_ostream"); + case SpecialSubKind::iostream: + return StringView("basic_iostream"); + } + LLVM_BUILTIN_UNREACHABLE; + } + + void printLeft(OutputStream &S) const override { + switch (SSK) { + case SpecialSubKind::allocator: + S += "std::allocator"; + break; + case SpecialSubKind::basic_string: + S += "std::basic_string"; + break; + case SpecialSubKind::string: + S += "std::basic_string, " + "std::allocator >"; + break; + case SpecialSubKind::istream: + S += "std::basic_istream >"; + break; + case SpecialSubKind::ostream: + S += "std::basic_ostream >"; + break; + case SpecialSubKind::iostream: + S += "std::basic_iostream >"; + break; + } + } +}; + +class SpecialSubstitution final : public Node { +public: + SpecialSubKind SSK; + + SpecialSubstitution(SpecialSubKind SSK_) + : Node(KSpecialSubstitution), SSK(SSK_) {} + + template void match(Fn F) const { F(SSK); } + + StringView getBaseName() const override { + switch (SSK) { + case SpecialSubKind::allocator: + return StringView("allocator"); + case SpecialSubKind::basic_string: + return StringView("basic_string"); + case SpecialSubKind::string: + return StringView("string"); + case SpecialSubKind::istream: + return StringView("istream"); + case SpecialSubKind::ostream: + return StringView("ostream"); + case SpecialSubKind::iostream: + return StringView("iostream"); + } + LLVM_BUILTIN_UNREACHABLE; + } + + void printLeft(OutputStream &S) const override { + switch (SSK) { + case SpecialSubKind::allocator: + S += "std::allocator"; + break; + case SpecialSubKind::basic_string: + S += "std::basic_string"; + break; + case SpecialSubKind::string: + S += "std::string"; + break; + case SpecialSubKind::istream: + S += "std::istream"; + break; + case SpecialSubKind::ostream: + S += "std::ostream"; + break; + case SpecialSubKind::iostream: + S += "std::iostream"; + break; + } + } +}; + +class CtorDtorName final : public Node { + const Node *Basename; + const bool IsDtor; + const int Variant; + +public: + CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_) + : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_), + Variant(Variant_) {} + + template void match(Fn F) const { F(Basename, IsDtor, Variant); } + + void printLeft(OutputStream &S) const override { + if (IsDtor) + S += "~"; + S += Basename->getBaseName(); + } +}; + +class DtorName : public Node { + const Node *Base; + +public: + DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {} + + template void match(Fn F) const { F(Base); } + + void printLeft(OutputStream &S) const override { + S += "~"; + Base->printLeft(S); + } +}; + +class UnnamedTypeName : public Node { + const StringView Count; + +public: + UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {} + + template void match(Fn F) const { F(Count); } + + void printLeft(OutputStream &S) const override { + S += "'unnamed"; + S += Count; + S += "\'"; + } +}; + +class ClosureTypeName : public Node { + NodeArray Params; + StringView Count; + +public: + ClosureTypeName(NodeArray Params_, StringView Count_) + : Node(KClosureTypeName), Params(Params_), Count(Count_) {} + + template void match(Fn F) const { F(Params, Count); } + + void printLeft(OutputStream &S) const override { + S += "\'lambda"; + S += Count; + S += "\'("; + Params.printWithComma(S); + S += ")"; + } +}; + +class StructuredBindingName : public Node { + NodeArray Bindings; +public: + StructuredBindingName(NodeArray Bindings_) + : Node(KStructuredBindingName), Bindings(Bindings_) {} + + template void match(Fn F) const { F(Bindings); } + + void printLeft(OutputStream &S) const override { + S += '['; + Bindings.printWithComma(S); + S += ']'; + } +}; + +// -- Expression Nodes -- + +class BinaryExpr : public Node { + const Node *LHS; + const StringView InfixOperator; + const Node *RHS; + +public: + BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_) + : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) { + } + + template void match(Fn F) const { F(LHS, InfixOperator, RHS); } + + void printLeft(OutputStream &S) const override { + // might be a template argument expression, then we need to disambiguate + // with parens. + if (InfixOperator == ">") + S += "("; + + S += "("; + LHS->print(S); + S += ") "; + S += InfixOperator; + S += " ("; + RHS->print(S); + S += ")"; + + if (InfixOperator == ">") + S += ")"; + } +}; + +class ArraySubscriptExpr : public Node { + const Node *Op1; + const Node *Op2; + +public: + ArraySubscriptExpr(const Node *Op1_, const Node *Op2_) + : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {} + + template void match(Fn F) const { F(Op1, Op2); } + + void printLeft(OutputStream &S) const override { + S += "("; + Op1->print(S); + S += ")["; + Op2->print(S); + S += "]"; + } +}; + +class PostfixExpr : public Node { + const Node *Child; + const StringView Operator; + +public: + PostfixExpr(const Node *Child_, StringView Operator_) + : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {} + + template void match(Fn F) const { F(Child, Operator); } + + void printLeft(OutputStream &S) const override { + S += "("; + Child->print(S); + S += ")"; + S += Operator; + } +}; + +class ConditionalExpr : public Node { + const Node *Cond; + const Node *Then; + const Node *Else; + +public: + ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_) + : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {} + + template void match(Fn F) const { F(Cond, Then, Else); } + + void printLeft(OutputStream &S) const override { + S += "("; + Cond->print(S); + S += ") ? ("; + Then->print(S); + S += ") : ("; + Else->print(S); + S += ")"; + } +}; + +class MemberExpr : public Node { + const Node *LHS; + const StringView Kind; + const Node *RHS; + +public: + MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_) + : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {} + + template void match(Fn F) const { F(LHS, Kind, RHS); } + + void printLeft(OutputStream &S) const override { + LHS->print(S); + S += Kind; + RHS->print(S); + } +}; + +class EnclosingExpr : public Node { + const StringView Prefix; + const Node *Infix; + const StringView Postfix; + +public: + EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_) + : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_), + Postfix(Postfix_) {} + + template void match(Fn F) const { F(Prefix, Infix, Postfix); } + + void printLeft(OutputStream &S) const override { + S += Prefix; + Infix->print(S); + S += Postfix; + } +}; + +class CastExpr : public Node { + // cast_kind(from) + const StringView CastKind; + const Node *To; + const Node *From; + +public: + CastExpr(StringView CastKind_, const Node *To_, const Node *From_) + : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {} + + template void match(Fn F) const { F(CastKind, To, From); } + + void printLeft(OutputStream &S) const override { + S += CastKind; + S += "<"; + To->printLeft(S); + S += ">("; + From->printLeft(S); + S += ")"; + } +}; + +class SizeofParamPackExpr : public Node { + const Node *Pack; + +public: + SizeofParamPackExpr(const Node *Pack_) + : Node(KSizeofParamPackExpr), Pack(Pack_) {} + + template void match(Fn F) const { F(Pack); } + + void printLeft(OutputStream &S) const override { + S += "sizeof...("; + ParameterPackExpansion PPE(Pack); + PPE.printLeft(S); + S += ")"; + } +}; + +class CallExpr : public Node { + const Node *Callee; + NodeArray Args; + +public: + CallExpr(const Node *Callee_, NodeArray Args_) + : Node(KCallExpr), Callee(Callee_), Args(Args_) {} + + template void match(Fn F) const { F(Callee, Args); } + + void printLeft(OutputStream &S) const override { + Callee->print(S); + S += "("; + Args.printWithComma(S); + S += ")"; + } +}; + +class NewExpr : public Node { + // new (expr_list) type(init_list) + NodeArray ExprList; + Node *Type; + NodeArray InitList; + bool IsGlobal; // ::operator new ? + bool IsArray; // new[] ? +public: + NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_, + bool IsArray_) + : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_), + IsGlobal(IsGlobal_), IsArray(IsArray_) {} + + template void match(Fn F) const { + F(ExprList, Type, InitList, IsGlobal, IsArray); + } + + void printLeft(OutputStream &S) const override { + if (IsGlobal) + S += "::operator "; + S += "new"; + if (IsArray) + S += "[]"; + S += ' '; + if (!ExprList.empty()) { + S += "("; + ExprList.printWithComma(S); + S += ")"; + } + Type->print(S); + if (!InitList.empty()) { + S += "("; + InitList.printWithComma(S); + S += ")"; + } + + } +}; + +class DeleteExpr : public Node { + Node *Op; + bool IsGlobal; + bool IsArray; + +public: + DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_) + : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} + + template void match(Fn F) const { F(Op, IsGlobal, IsArray); } + + void printLeft(OutputStream &S) const override { + if (IsGlobal) + S += "::"; + S += "delete"; + if (IsArray) + S += "[] "; + Op->print(S); + } +}; + +class PrefixExpr : public Node { + StringView Prefix; + Node *Child; + +public: + PrefixExpr(StringView Prefix_, Node *Child_) + : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {} + + template void match(Fn F) const { F(Prefix, Child); } + + void printLeft(OutputStream &S) const override { + S += Prefix; + S += "("; + Child->print(S); + S += ")"; + } +}; + +class FunctionParam : public Node { + StringView Number; + +public: + FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {} + + template void match(Fn F) const { F(Number); } + + void printLeft(OutputStream &S) const override { + S += "fp"; + S += Number; + } +}; + +class ConversionExpr : public Node { + const Node *Type; + NodeArray Expressions; + +public: + ConversionExpr(const Node *Type_, NodeArray Expressions_) + : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {} + + template void match(Fn F) const { F(Type, Expressions); } + + void printLeft(OutputStream &S) const override { + S += "("; + Type->print(S); + S += ")("; + Expressions.printWithComma(S); + S += ")"; + } +}; + +class InitListExpr : public Node { + const Node *Ty; + NodeArray Inits; +public: + InitListExpr(const Node *Ty_, NodeArray Inits_) + : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {} + + template void match(Fn F) const { F(Ty, Inits); } + + void printLeft(OutputStream &S) const override { + if (Ty) + Ty->print(S); + S += '{'; + Inits.printWithComma(S); + S += '}'; + } +}; + +class BracedExpr : public Node { + const Node *Elem; + const Node *Init; + bool IsArray; +public: + BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_) + : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {} + + template void match(Fn F) const { F(Elem, Init, IsArray); } + + void printLeft(OutputStream &S) const override { + if (IsArray) { + S += '['; + Elem->print(S); + S += ']'; + } else { + S += '.'; + Elem->print(S); + } + if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr) + S += " = "; + Init->print(S); + } +}; + +class BracedRangeExpr : public Node { + const Node *First; + const Node *Last; + const Node *Init; +public: + BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_) + : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {} + + template void match(Fn F) const { F(First, Last, Init); } + + void printLeft(OutputStream &S) const override { + S += '['; + First->print(S); + S += " ... "; + Last->print(S); + S += ']'; + if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr) + S += " = "; + Init->print(S); + } +}; + +class FoldExpr : public Node { + const Node *Pack, *Init; + StringView OperatorName; + bool IsLeftFold; + +public: + FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_, + const Node *Init_) + : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_), + IsLeftFold(IsLeftFold_) {} + + template void match(Fn F) const { + F(IsLeftFold, OperatorName, Pack, Init); + } + + void printLeft(OutputStream &S) const override { + auto PrintPack = [&] { + S += '('; + ParameterPackExpansion(Pack).print(S); + S += ')'; + }; + + S += '('; + + if (IsLeftFold) { + // init op ... op pack + if (Init != nullptr) { + Init->print(S); + S += ' '; + S += OperatorName; + S += ' '; + } + // ... op pack + S += "... "; + S += OperatorName; + S += ' '; + PrintPack(); + } else { // !IsLeftFold + // pack op ... + PrintPack(); + S += ' '; + S += OperatorName; + S += " ..."; + // pack op ... op init + if (Init != nullptr) { + S += ' '; + S += OperatorName; + S += ' '; + Init->print(S); + } + } + S += ')'; + } +}; + +class ThrowExpr : public Node { + const Node *Op; + +public: + ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {} + + template void match(Fn F) const { F(Op); } + + void printLeft(OutputStream &S) const override { + S += "throw "; + Op->print(S); + } +}; + +class BoolExpr : public Node { + bool Value; + +public: + BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {} + + template void match(Fn F) const { F(Value); } + + void printLeft(OutputStream &S) const override { + S += Value ? StringView("true") : StringView("false"); + } +}; + +class IntegerCastExpr : public Node { + // ty(integer) + const Node *Ty; + StringView Integer; + +public: + IntegerCastExpr(const Node *Ty_, StringView Integer_) + : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {} + + template void match(Fn F) const { F(Ty, Integer); } + + void printLeft(OutputStream &S) const override { + S += "("; + Ty->print(S); + S += ")"; + S += Integer; + } +}; + +class IntegerLiteral : public Node { + StringView Type; + StringView Value; + +public: + IntegerLiteral(StringView Type_, StringView Value_) + : Node(KIntegerLiteral), Type(Type_), Value(Value_) {} + + template void match(Fn F) const { F(Type, Value); } + + void printLeft(OutputStream &S) const override { + if (Type.size() > 3) { + S += "("; + S += Type; + S += ")"; + } + + if (Value[0] == 'n') { + S += "-"; + S += Value.dropFront(1); + } else + S += Value; + + if (Type.size() <= 3) + S += Type; + } +}; + +template struct FloatData; + +namespace float_literal_impl { +constexpr Node::Kind getFloatLiteralKind(float *) { + return Node::KFloatLiteral; +} +constexpr Node::Kind getFloatLiteralKind(double *) { + return Node::KDoubleLiteral; +} +constexpr Node::Kind getFloatLiteralKind(long double *) { + return Node::KLongDoubleLiteral; +} +} + +template class FloatLiteralImpl : public Node { + const StringView Contents; + + static constexpr Kind KindForClass = + float_literal_impl::getFloatLiteralKind((Float *)nullptr); + +public: + FloatLiteralImpl(StringView Contents_) + : Node(KindForClass), Contents(Contents_) {} + + template void match(Fn F) const { F(Contents); } + + void printLeft(OutputStream &s) const override { + const char *first = Contents.begin(); + const char *last = Contents.end() + 1; + + const size_t N = FloatData::mangled_size; + if (static_cast(last - first) > N) { + last = first + N; + union { + Float value; + char buf[sizeof(Float)]; + }; + const char *t = first; + char *e = buf; + for (; t != last; ++t, ++e) { + unsigned d1 = isdigit(*t) ? static_cast(*t - '0') + : static_cast(*t - 'a' + 10); + ++t; + unsigned d0 = isdigit(*t) ? static_cast(*t - '0') + : static_cast(*t - 'a' + 10); + *e = static_cast((d1 << 4) + d0); + } +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::reverse(buf, e); +#endif + char num[FloatData::max_demangled_size] = {0}; + int n = snprintf(num, sizeof(num), FloatData::spec, value); + s += StringView(num, num + n); + } + } +}; + +using FloatLiteral = FloatLiteralImpl; +using DoubleLiteral = FloatLiteralImpl; +using LongDoubleLiteral = FloatLiteralImpl; + +/// Visit the node. Calls \c F(P), where \c P is the node cast to the +/// appropriate derived class. +template +void Node::visit(Fn F) const { + switch (K) { +#define CASE(X) case K ## X: return F(static_cast(this)); + FOR_EACH_NODE_KIND(CASE) +#undef CASE + } + assert(0 && "unknown mangling node kind"); +} + +/// Determine the kind of a node from its type. +template struct NodeKind; +#define SPECIALIZATION(X) \ + template<> struct NodeKind { \ + static constexpr Node::Kind Kind = Node::K##X; \ + static constexpr const char *name() { return #X; } \ + }; +FOR_EACH_NODE_KIND(SPECIALIZATION) +#undef SPECIALIZATION + +#undef FOR_EACH_NODE_KIND + +template +class PODSmallVector { + static_assert(std::is_pod::value, + "T is required to be a plain old data type"); + + T* First; + T* Last; + T* Cap; + T Inline[N]; + + bool isInline() const { return First == Inline; } + + void clearInline() { + First = Inline; + Last = Inline; + Cap = Inline + N; + } + + void reserve(size_t NewCap) { + size_t S = size(); + if (isInline()) { + auto* Tmp = static_cast(std::malloc(NewCap * sizeof(T))); + if (Tmp == nullptr) + std::terminate(); + std::copy(First, Last, Tmp); + First = Tmp; + } else { + First = static_cast(std::realloc(First, NewCap * sizeof(T))); + if (First == nullptr) + std::terminate(); + } + Last = First + S; + Cap = First + NewCap; + } + +public: + PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {} + + PODSmallVector(const PODSmallVector&) = delete; + PODSmallVector& operator=(const PODSmallVector&) = delete; + + PODSmallVector(PODSmallVector&& Other) : PODSmallVector() { + if (Other.isInline()) { + std::copy(Other.begin(), Other.end(), First); + Last = First + Other.size(); + Other.clear(); + return; + } + + First = Other.First; + Last = Other.Last; + Cap = Other.Cap; + Other.clearInline(); + } + + PODSmallVector& operator=(PODSmallVector&& Other) { + if (Other.isInline()) { + if (!isInline()) { + std::free(First); + clearInline(); + } + std::copy(Other.begin(), Other.end(), First); + Last = First + Other.size(); + Other.clear(); + return *this; + } + + if (isInline()) { + First = Other.First; + Last = Other.Last; + Cap = Other.Cap; + Other.clearInline(); + return *this; + } + + std::swap(First, Other.First); + std::swap(Last, Other.Last); + std::swap(Cap, Other.Cap); + Other.clear(); + return *this; + } + + void push_back(const T& Elem) { + if (Last == Cap) + reserve(size() * 2); + *Last++ = Elem; + } + + void pop_back() { + assert(Last != First && "Popping empty vector!"); + --Last; + } + + void dropBack(size_t Index) { + assert(Index <= size() && "dropBack() can't expand!"); + Last = First + Index; + } + + T* begin() { return First; } + T* end() { return Last; } + + bool empty() const { return First == Last; } + size_t size() const { return static_cast(Last - First); } + T& back() { + assert(Last != First && "Calling back() on empty vector!"); + return *(Last - 1); + } + T& operator[](size_t Index) { + assert(Index < size() && "Invalid access!"); + return *(begin() + Index); + } + void clear() { Last = First; } + + ~PODSmallVector() { + if (!isInline()) + std::free(First); + } +}; + +template struct AbstractManglingParser { + const char *First; + const char *Last; + + // Name stack, this is used by the parser to hold temporary names that were + // parsed. The parser collapses multiple names into new nodes to construct + // the AST. Once the parser is finished, names.size() == 1. + PODSmallVector Names; + + // Substitution table. Itanium supports name substitutions as a means of + // compression. The string "S42_" refers to the 44nd entry (base-36) in this + // table. + PODSmallVector Subs; + + // Template parameter table. Like the above, but referenced like "T42_". + // This has a smaller size compared to Subs and Names because it can be + // stored on the stack. + PODSmallVector TemplateParams; + + // Set of unresolved forward references. These can occur in a + // conversion operator's type, and are resolved in the enclosing . + PODSmallVector ForwardTemplateRefs; + + bool TryToParseTemplateArgs = true; + bool PermitForwardTemplateReferences = false; + bool ParsingLambdaParams = false; + + Alloc ASTAllocator; + + AbstractManglingParser(const char *First_, const char *Last_) + : First(First_), Last(Last_) {} + + Derived &getDerived() { return static_cast(*this); } + + void reset(const char *First_, const char *Last_) { + First = First_; + Last = Last_; + Names.clear(); + Subs.clear(); + TemplateParams.clear(); + ParsingLambdaParams = false; + TryToParseTemplateArgs = true; + PermitForwardTemplateReferences = false; + ASTAllocator.reset(); + } + + template Node *make(Args &&... args) { + return ASTAllocator.template makeNode(std::forward(args)...); + } + + template NodeArray makeNodeArray(It begin, It end) { + size_t sz = static_cast(end - begin); + void *mem = ASTAllocator.allocateNodeArray(sz); + Node **data = new (mem) Node *[sz]; + std::copy(begin, end, data); + return NodeArray(data, sz); + } + + NodeArray popTrailingNodeArray(size_t FromPosition) { + assert(FromPosition <= Names.size()); + NodeArray res = + makeNodeArray(Names.begin() + (long)FromPosition, Names.end()); + Names.dropBack(FromPosition); + return res; + } + + bool consumeIf(StringView S) { + if (StringView(First, Last).startsWith(S)) { + First += S.size(); + return true; + } + return false; + } + + bool consumeIf(char C) { + if (First != Last && *First == C) { + ++First; + return true; + } + return false; + } + + char consume() { return First != Last ? *First++ : '\0'; } + + char look(unsigned Lookahead = 0) { + if (static_cast(Last - First) <= Lookahead) + return '\0'; + return First[Lookahead]; + } + + size_t numLeft() const { return static_cast(Last - First); } + + StringView parseNumber(bool AllowNegative = false); + Qualifiers parseCVQualifiers(); + bool parsePositiveInteger(size_t *Out); + StringView parseBareSourceName(); + + bool parseSeqId(size_t *Out); + Node *parseSubstitution(); + Node *parseTemplateParam(); + Node *parseTemplateArgs(bool TagTemplates = false); + Node *parseTemplateArg(); + + /// Parse the production. + Node *parseExpr(); + Node *parsePrefixExpr(StringView Kind); + Node *parseBinaryExpr(StringView Kind); + Node *parseIntegerLiteral(StringView Lit); + Node *parseExprPrimary(); + template Node *parseFloatingLiteral(); + Node *parseFunctionParam(); + Node *parseNewExpr(); + Node *parseConversionExpr(); + Node *parseBracedExpr(); + Node *parseFoldExpr(); + + /// Parse the production. + Node *parseType(); + Node *parseFunctionType(); + Node *parseVectorType(); + Node *parseDecltype(); + Node *parseArrayType(); + Node *parsePointerToMemberType(); + Node *parseClassEnumType(); + Node *parseQualifiedType(); + + Node *parseEncoding(); + bool parseCallOffset(); + Node *parseSpecialName(); + + /// Holds some extra information about a that is being parsed. This + /// information is only pertinent if the refers to an . + struct NameState { + bool CtorDtorConversion = false; + bool EndsWithTemplateArgs = false; + Qualifiers CVQualifiers = QualNone; + FunctionRefQual ReferenceQualifier = FrefQualNone; + size_t ForwardTemplateRefsBegin; + + NameState(AbstractManglingParser *Enclosing) + : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {} + }; + + bool resolveForwardTemplateRefs(NameState &State) { + size_t I = State.ForwardTemplateRefsBegin; + size_t E = ForwardTemplateRefs.size(); + for (; I < E; ++I) { + size_t Idx = ForwardTemplateRefs[I]->Index; + if (Idx >= TemplateParams.size()) + return true; + ForwardTemplateRefs[I]->Ref = TemplateParams[Idx]; + } + ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin); + return false; + } + + /// Parse the production> + Node *parseName(NameState *State = nullptr); + Node *parseLocalName(NameState *State); + Node *parseOperatorName(NameState *State); + Node *parseUnqualifiedName(NameState *State); + Node *parseUnnamedTypeName(NameState *State); + Node *parseSourceName(NameState *State); + Node *parseUnscopedName(NameState *State); + Node *parseNestedName(NameState *State); + Node *parseCtorDtorName(Node *&SoFar, NameState *State); + + Node *parseAbiTags(Node *N); + + /// Parse the production. + Node *parseUnresolvedName(); + Node *parseSimpleId(); + Node *parseBaseUnresolvedName(); + Node *parseUnresolvedType(); + Node *parseDestructorName(); + + /// Top-level entry point into the parser. + Node *parse(); +}; + +const char* parse_discriminator(const char* first, const char* last); + +// ::= // N +// ::= # See Scope Encoding below // Z +// ::= +// ::= +// +// ::= +// ::= +template +Node *AbstractManglingParser::parseName(NameState *State) { + consumeIf('L'); // extension + + if (look() == 'N') + return getDerived().parseNestedName(State); + if (look() == 'Z') + return getDerived().parseLocalName(State); + + // ::= + if (look() == 'S' && look(1) != 't') { + Node *S = getDerived().parseSubstitution(); + if (S == nullptr) + return nullptr; + if (look() != 'I') + return nullptr; + Node *TA = getDerived().parseTemplateArgs(State != nullptr); + if (TA == nullptr) + return nullptr; + if (State) State->EndsWithTemplateArgs = true; + return make(S, TA); + } + + Node *N = getDerived().parseUnscopedName(State); + if (N == nullptr) + return nullptr; + // ::= + if (look() == 'I') { + Subs.push_back(N); + Node *TA = getDerived().parseTemplateArgs(State != nullptr); + if (TA == nullptr) + return nullptr; + if (State) State->EndsWithTemplateArgs = true; + return make(N, TA); + } + // ::= + return N; +} + +// := Z E [] +// := Z E s [] +// := Z Ed [ ] _ +template +Node *AbstractManglingParser::parseLocalName(NameState *State) { + if (!consumeIf('Z')) + return nullptr; + Node *Encoding = getDerived().parseEncoding(); + if (Encoding == nullptr || !consumeIf('E')) + return nullptr; + + if (consumeIf('s')) { + First = parse_discriminator(First, Last); + auto *StringLitName = make("string literal"); + if (!StringLitName) + return nullptr; + return make(Encoding, StringLitName); + } + + if (consumeIf('d')) { + parseNumber(true); + if (!consumeIf('_')) + return nullptr; + Node *N = getDerived().parseName(State); + if (N == nullptr) + return nullptr; + return make(Encoding, N); + } + + Node *Entity = getDerived().parseName(State); + if (Entity == nullptr) + return nullptr; + First = parse_discriminator(First, Last); + return make(Encoding, Entity); +} + +// ::= +// ::= St # ::std:: +// extension ::= StL +template +Node * +AbstractManglingParser::parseUnscopedName(NameState *State) { + if (consumeIf("StL") || consumeIf("St")) { + Node *R = getDerived().parseUnqualifiedName(State); + if (R == nullptr) + return nullptr; + return make(R); + } + return getDerived().parseUnqualifiedName(State); +} + +// ::= [abi-tags] +// ::= +// ::= +// ::= +// ::= DC + E # structured binding declaration +template +Node * +AbstractManglingParser::parseUnqualifiedName(NameState *State) { + // s are special-cased in parseNestedName(). + Node *Result; + if (look() == 'U') + Result = getDerived().parseUnnamedTypeName(State); + else if (look() >= '1' && look() <= '9') + Result = getDerived().parseSourceName(State); + else if (consumeIf("DC")) { + size_t BindingsBegin = Names.size(); + do { + Node *Binding = getDerived().parseSourceName(State); + if (Binding == nullptr) + return nullptr; + Names.push_back(Binding); + } while (!consumeIf('E')); + Result = make(popTrailingNodeArray(BindingsBegin)); + } else + Result = getDerived().parseOperatorName(State); + if (Result != nullptr) + Result = getDerived().parseAbiTags(Result); + return Result; +} + +// ::= Ut [] _ +// ::= +// +// ::= Ul E [ ] _ +// +// ::= + # Parameter types or "v" if the lambda has no parameters +template +Node * +AbstractManglingParser::parseUnnamedTypeName(NameState *) { + if (consumeIf("Ut")) { + StringView Count = parseNumber(); + if (!consumeIf('_')) + return nullptr; + return make(Count); + } + if (consumeIf("Ul")) { + NodeArray Params; + SwapAndRestore SwapParams(ParsingLambdaParams, true); + if (!consumeIf("vE")) { + size_t ParamsBegin = Names.size(); + do { + Node *P = getDerived().parseType(); + if (P == nullptr) + return nullptr; + Names.push_back(P); + } while (!consumeIf('E')); + Params = popTrailingNodeArray(ParamsBegin); + } + StringView Count = parseNumber(); + if (!consumeIf('_')) + return nullptr; + return make(Params, Count); + } + return nullptr; +} + +// ::= +template +Node *AbstractManglingParser::parseSourceName(NameState *) { + size_t Length = 0; + if (parsePositiveInteger(&Length)) + return nullptr; + if (numLeft() < Length || Length == 0) + return nullptr; + StringView Name(First, First + Length); + First += Length; + if (Name.startsWith("_GLOBAL__N")) + return make("(anonymous namespace)"); + return make(Name); +} + +// ::= aa # && +// ::= ad # & (unary) +// ::= an # & +// ::= aN # &= +// ::= aS # = +// ::= cl # () +// ::= cm # , +// ::= co # ~ +// ::= cv # (cast) +// ::= da # delete[] +// ::= de # * (unary) +// ::= dl # delete +// ::= dv # / +// ::= dV # /= +// ::= eo # ^ +// ::= eO # ^= +// ::= eq # == +// ::= ge # >= +// ::= gt # > +// ::= ix # [] +// ::= le # <= +// ::= li # operator "" +// ::= ls # << +// ::= lS # <<= +// ::= lt # < +// ::= mi # - +// ::= mI # -= +// ::= ml # * +// ::= mL # *= +// ::= mm # -- (postfix in context) +// ::= na # new[] +// ::= ne # != +// ::= ng # - (unary) +// ::= nt # ! +// ::= nw # new +// ::= oo # || +// ::= or # | +// ::= oR # |= +// ::= pm # ->* +// ::= pl # + +// ::= pL # += +// ::= pp # ++ (postfix in context) +// ::= ps # + (unary) +// ::= pt # -> +// ::= qu # ? +// ::= rm # % +// ::= rM # %= +// ::= rs # >> +// ::= rS # >>= +// ::= ss # <=> C++2a +// ::= v # vendor extended operator +template +Node * +AbstractManglingParser::parseOperatorName(NameState *State) { + switch (look()) { + case 'a': + switch (look(1)) { + case 'a': + First += 2; + return make("operator&&"); + case 'd': + case 'n': + First += 2; + return make("operator&"); + case 'N': + First += 2; + return make("operator&="); + case 'S': + First += 2; + return make("operator="); + } + return nullptr; + case 'c': + switch (look(1)) { + case 'l': + First += 2; + return make("operator()"); + case 'm': + First += 2; + return make("operator,"); + case 'o': + First += 2; + return make("operator~"); + // ::= cv # (cast) + case 'v': { + First += 2; + SwapAndRestore SaveTemplate(TryToParseTemplateArgs, false); + // If we're parsing an encoding, State != nullptr and the conversion + // operators' could have a that refers to some + // s further ahead in the mangled name. + SwapAndRestore SavePermit(PermitForwardTemplateReferences, + PermitForwardTemplateReferences || + State != nullptr); + Node *Ty = getDerived().parseType(); + if (Ty == nullptr) + return nullptr; + if (State) State->CtorDtorConversion = true; + return make(Ty); + } + } + return nullptr; + case 'd': + switch (look(1)) { + case 'a': + First += 2; + return make("operator delete[]"); + case 'e': + First += 2; + return make("operator*"); + case 'l': + First += 2; + return make("operator delete"); + case 'v': + First += 2; + return make("operator/"); + case 'V': + First += 2; + return make("operator/="); + } + return nullptr; + case 'e': + switch (look(1)) { + case 'o': + First += 2; + return make("operator^"); + case 'O': + First += 2; + return make("operator^="); + case 'q': + First += 2; + return make("operator=="); + } + return nullptr; + case 'g': + switch (look(1)) { + case 'e': + First += 2; + return make("operator>="); + case 't': + First += 2; + return make("operator>"); + } + return nullptr; + case 'i': + if (look(1) == 'x') { + First += 2; + return make("operator[]"); + } + return nullptr; + case 'l': + switch (look(1)) { + case 'e': + First += 2; + return make("operator<="); + // ::= li # operator "" + case 'i': { + First += 2; + Node *SN = getDerived().parseSourceName(State); + if (SN == nullptr) + return nullptr; + return make(SN); + } + case 's': + First += 2; + return make("operator<<"); + case 'S': + First += 2; + return make("operator<<="); + case 't': + First += 2; + return make("operator<"); + } + return nullptr; + case 'm': + switch (look(1)) { + case 'i': + First += 2; + return make("operator-"); + case 'I': + First += 2; + return make("operator-="); + case 'l': + First += 2; + return make("operator*"); + case 'L': + First += 2; + return make("operator*="); + case 'm': + First += 2; + return make("operator--"); + } + return nullptr; + case 'n': + switch (look(1)) { + case 'a': + First += 2; + return make("operator new[]"); + case 'e': + First += 2; + return make("operator!="); + case 'g': + First += 2; + return make("operator-"); + case 't': + First += 2; + return make("operator!"); + case 'w': + First += 2; + return make("operator new"); + } + return nullptr; + case 'o': + switch (look(1)) { + case 'o': + First += 2; + return make("operator||"); + case 'r': + First += 2; + return make("operator|"); + case 'R': + First += 2; + return make("operator|="); + } + return nullptr; + case 'p': + switch (look(1)) { + case 'm': + First += 2; + return make("operator->*"); + case 'l': + First += 2; + return make("operator+"); + case 'L': + First += 2; + return make("operator+="); + case 'p': + First += 2; + return make("operator++"); + case 's': + First += 2; + return make("operator+"); + case 't': + First += 2; + return make("operator->"); + } + return nullptr; + case 'q': + if (look(1) == 'u') { + First += 2; + return make("operator?"); + } + return nullptr; + case 'r': + switch (look(1)) { + case 'm': + First += 2; + return make("operator%"); + case 'M': + First += 2; + return make("operator%="); + case 's': + First += 2; + return make("operator>>"); + case 'S': + First += 2; + return make("operator>>="); + } + return nullptr; + case 's': + if (look(1) == 's') { + First += 2; + return make("operator<=>"); + } + return nullptr; + // ::= v # vendor extended operator + case 'v': + if (std::isdigit(look(1))) { + First += 2; + Node *SN = getDerived().parseSourceName(State); + if (SN == nullptr) + return nullptr; + return make(SN); + } + return nullptr; + } + return nullptr; +} + +// ::= C1 # complete object constructor +// ::= C2 # base object constructor +// ::= C3 # complete object allocating constructor +// extension ::= C5 # ? +// ::= D0 # deleting destructor +// ::= D1 # complete object destructor +// ::= D2 # base object destructor +// extension ::= D5 # ? +template +Node * +AbstractManglingParser::parseCtorDtorName(Node *&SoFar, + NameState *State) { + if (SoFar->getKind() == Node::KSpecialSubstitution) { + auto SSK = static_cast(SoFar)->SSK; + switch (SSK) { + case SpecialSubKind::string: + case SpecialSubKind::istream: + case SpecialSubKind::ostream: + case SpecialSubKind::iostream: + SoFar = make(SSK); + if (!SoFar) + return nullptr; + break; + default: + break; + } + } + + if (consumeIf('C')) { + bool IsInherited = consumeIf('I'); + if (look() != '1' && look() != '2' && look() != '3' && look() != '5') + return nullptr; + int Variant = look() - '0'; + ++First; + if (State) State->CtorDtorConversion = true; + if (IsInherited) { + if (getDerived().parseName(State) == nullptr) + return nullptr; + } + return make(SoFar, false, Variant); + } + + if (look() == 'D' && + (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) { + int Variant = look(1) - '0'; + First += 2; + if (State) State->CtorDtorConversion = true; + return make(SoFar, true, Variant); + } + + return nullptr; +} + +// ::= N [] [] E +// ::= N [] [] E +// +// ::= +// ::= +// ::= +// ::= +// ::= # empty +// ::= +// ::= +// extension ::= L +// +// := [] M +// +// ::=