aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmir Ayupov <aaupov@fb.com>2024-07-18 20:59:32 -0700
committerAmir Ayupov <aaupov@fb.com>2024-07-18 20:59:32 -0700
commit1f039a25ee9f32ddceae081125b51948013b58d9 (patch)
tree0469bddd47d51778d77629c5f16f24ab74f38a4d
parent99c26d6d379be17d4045685969654c0341b25425 (diff)
parent9b007a199d650f47072fe112b8315f3b3bebb27d (diff)
downloadllvm-users/aaupov/spr/main.mcnfc-use-stdmap-for-addressprobesmap.zip
llvm-users/aaupov/spr/main.mcnfc-use-stdmap-for-addressprobesmap.tar.gz
llvm-users/aaupov/spr/main.mcnfc-use-stdmap-for-addressprobesmap.tar.bz2
[𝘀𝗽𝗿] changes introduced through rebaseusers/aaupov/spr/main.mcnfc-use-stdmap-for-addressprobesmap
Created using spr 1.3.4 [skip ci]
-rw-r--r--bolt/include/bolt/Core/BinaryContext.h11
-rw-r--r--bolt/include/bolt/Core/BinaryFunction.h11
-rw-r--r--bolt/include/bolt/Core/MCPlusBuilder.h13
-rw-r--r--bolt/lib/Core/BinaryContext.cpp10
-rw-r--r--bolt/lib/Core/BinaryFunction.cpp47
-rw-r--r--bolt/lib/Passes/IndirectCallPromotion.cpp4
-rw-r--r--bolt/lib/Profile/DataAggregator.cpp2
-rw-r--r--bolt/lib/Profile/YAMLProfileWriter.cpp2
-rw-r--r--bolt/lib/Rewrite/PseudoProbeRewriter.cpp15
-rw-r--r--bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp13
-rw-r--r--bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp3
-rw-r--r--bolt/lib/Target/X86/X86MCPlusBuilder.cpp105
-rw-r--r--bolt/test/X86/Inputs/jump-table-fixed-ref-pic.s2
-rw-r--r--bolt/test/X86/jump-table-fixed-ref-pic.test12
-rw-r--r--clang/include/clang/Basic/BuiltinsAMDGPU.def18
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp62
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp21
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.cpp18
-rw-r--r--clang/lib/Lex/DependencyDirectivesScanner.cpp13
-rw-r--r--clang/test/CodeGen/attr-counted-by.c54
-rw-r--r--clang/test/CodeGen/math-libcalls-tbaa.cpp9
-rw-r--r--clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load.cl172
-rw-r--r--clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-store.cl48
-rw-r--r--clang/test/Driver/hexagon-toolchain-linux.c33
-rw-r--r--clang/test/Preprocessor/aarch64-target-features.c351
-rw-r--r--clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-load-error.cl33
-rw-r--r--clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-store-error.cl26
-rw-r--r--clang/unittests/Lex/DependencyDirectivesScannerTest.cpp17
-rw-r--r--compiler-rt/cmake/base-config-ix.cmake4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp3
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp118
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp7
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp2
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp15
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_win.cpp8
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp8
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp23
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp2
-rw-r--r--compiler-rt/test/CMakeLists.txt2
-rw-r--r--compiler-rt/test/asan/CMakeLists.txt56
-rw-r--r--compiler-rt/test/ctx_profile/CMakeLists.txt20
-rw-r--r--compiler-rt/test/fuzzer/CMakeLists.txt18
-rw-r--r--compiler-rt/test/gwp_asan/CMakeLists.txt4
-rw-r--r--compiler-rt/test/interception/CMakeLists.txt2
-rw-r--r--compiler-rt/test/memprof/CMakeLists.txt20
-rw-r--r--compiler-rt/test/msan/CMakeLists.txt4
-rw-r--r--compiler-rt/test/nsan/CMakeLists.txt4
-rw-r--r--compiler-rt/test/rtsan/CMakeLists.txt22
-rw-r--r--compiler-rt/test/sanitizer_common/CMakeLists.txt16
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_i386.cpp17
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_x86_64.cpp19
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp11
-rw-r--r--compiler-rt/test/scudo/standalone/CMakeLists.txt34
-rw-r--r--compiler-rt/test/tsan/CMakeLists.txt22
-rw-r--r--flang/docs/Extensions.md7
-rw-r--r--flang/lib/Parser/Fortran-parsers.cpp16
-rw-r--r--flang/lib/Parser/prescan.cpp16
-rw-r--r--flang/lib/Semantics/definable.cpp5
-rw-r--r--flang/lib/Semantics/expression.cpp2
-rw-r--r--flang/runtime/unit.cpp1
-rw-r--r--flang/test/Preprocessing/directive-contin-with-pp.F9017
-rw-r--r--flang/test/Semantics/array-constr-values.f902
-rw-r--r--flang/test/Semantics/assign10.f906
-rw-r--r--flang/test/Semantics/associate03.f9079
-rw-r--r--flang/test/Semantics/parent-comp-name.f9070
-rw-r--r--flang/test/Semantics/struct03.f907
-rw-r--r--libc/CMakeLists.txt2
-rw-r--r--libc/cmake/modules/LLVMLibCHeaderRules.cmake102
-rw-r--r--libc/config/linux/api.td2
-rw-r--r--libc/config/linux/x86_64/headers.txt3
-rw-r--r--libc/include/CMakeLists.txt379
-rw-r--r--libc/newhdrgen/class_implementation/classes/include.py17
-rw-r--r--libc/newhdrgen/gpu_headers.py1
-rw-r--r--libc/newhdrgen/header.py7
-rw-r--r--libc/newhdrgen/yaml/arpa/inet.yaml (renamed from libc/newhdrgen/yaml/arpa/arpa_inet.yaml)0
-rw-r--r--libc/newhdrgen/yaml/gpu/rpc.yaml (renamed from libc/newhdrgen/yaml/gpu/gpu_rpc.yaml)0
-rw-r--r--libc/newhdrgen/yaml/math.yaml64
-rw-r--r--libc/newhdrgen/yaml/sys/auxv.yaml (renamed from libc/newhdrgen/yaml/sys/sys_auxv.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/epoll.yaml (renamed from libc/newhdrgen/yaml/sys/sys_epoll.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/ioctl.yaml (renamed from libc/newhdrgen/yaml/sys/sys_ioctl.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/mman.yaml (renamed from libc/newhdrgen/yaml/sys/sys_mman.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/prctl.yaml (renamed from libc/newhdrgen/yaml/sys/sys_prctl.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/random.yaml (renamed from libc/newhdrgen/yaml/sys/sys_random.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/resource.yaml (renamed from libc/newhdrgen/yaml/sys/sys_resource.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/select.yaml (renamed from libc/newhdrgen/yaml/sys/sys_select.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/sendfile.yaml (renamed from libc/newhdrgen/yaml/sys/sys_sendfile.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/socket.yaml (renamed from libc/newhdrgen/yaml/sys/sys_socket.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/stat.yaml (renamed from libc/newhdrgen/yaml/sys/sys_stat.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/statvfs.yaml (renamed from libc/newhdrgen/yaml/sys/sys_statvfs.yaml)2
-rw-r--r--libc/newhdrgen/yaml/sys/syscall.yaml (renamed from libc/newhdrgen/yaml/sys/sys_syscall.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/time.yaml (renamed from libc/newhdrgen/yaml/sys/sys_time.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/types.yaml (renamed from libc/newhdrgen/yaml/sys/sys_types.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/utsname.yaml (renamed from libc/newhdrgen/yaml/sys/sys_utsname.yaml)0
-rw-r--r--libc/newhdrgen/yaml/sys/wait.yaml (renamed from libc/newhdrgen/yaml/sys/sys_wait.yaml)0
-rw-r--r--libc/newhdrgen/yaml_to_classes.py4
-rw-r--r--libc/src/sys/statvfs/linux/CMakeLists.txt6
-rw-r--r--libc/utils/MPFRWrapper/CMakeLists.txt2
-rw-r--r--libcxx/benchmarks/CMakeLists.txt1
-rw-r--r--libcxx/benchmarks/algorithms/set_intersection.bench.cpp184
-rw-r--r--libcxx/cmake/caches/Apple.cmake3
-rw-r--r--libcxx/docs/FeatureTestMacroTable.rst4
-rw-r--r--libcxx/docs/ReleaseNotes/19.rst5
-rw-r--r--libcxx/docs/Status/Cxx23Issues.csv4
-rw-r--r--libcxx/docs/Status/Cxx23Papers.csv2
-rw-r--r--libcxx/docs/Status/Cxx2cIssues.csv2
-rw-r--r--libcxx/include/CMakeLists.txt2
-rw-r--r--libcxx/include/__algorithm/iterator_operations.h54
-rw-r--r--libcxx/include/__algorithm/lower_bound.h54
-rw-r--r--libcxx/include/__algorithm/set_intersection.h122
-rw-r--r--libcxx/include/__memory/allocator_traits.h1
-rw-r--r--libcxx/include/__memory/inout_ptr.h109
-rw-r--r--libcxx/include/__memory/out_ptr.h101
-rw-r--r--libcxx/include/__memory/pointer_traits.h70
-rw-r--r--libcxx/include/memory18
-rw-r--r--libcxx/include/module.modulemap2
-rw-r--r--libcxx/include/version4
-rw-r--r--libcxx/modules/std/memory.inc10
-rw-r--r--libcxx/test/configs/apple-libc++-shared.cfg.in51
-rw-r--r--libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/ranges_set_intersection.pass.cpp71
-rw-r--r--libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_complexity.pass.cpp404
-rw-r--r--libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp11
-rw-r--r--libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp63
-rw-r--r--libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp28
-rw-r--r--libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp32
-rw-r--r--libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp32
-rw-r--r--libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp8
-rw-r--r--libcxx/test/std/ranges/range.adaptors/range.drop/types.h10
-rw-r--r--libcxx/test/std/ranges/range.adaptors/range.transform/types.h6
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.general.pass.cpp206
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp34
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.convert.pass.cpp61
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.ctor.pass.cpp61
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.verify.cpp29
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.general.pass.cpp230
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp34
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.convert.pass.cpp61
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.ctor.pass.cpp59
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.verify.cpp29
-rw-r--r--libcxx/test/std/utilities/smartptr/adapt/types.h86
-rw-r--r--libcxx/test/support/test_iterators.h184
-rwxr-xr-xlibcxx/utils/ci/apple-install-libcxx.sh14
-rwxr-xr-xlibcxx/utils/generate_feature_test_macro_components.py1
-rw-r--r--libcxxabi/src/vendor/apple/shims.cpp65
-rw-r--r--libcxxabi/test/configs/apple-libc++abi-shared.cfg.in49
-rw-r--r--lldb/bindings/headers.swig1
-rw-r--r--lldb/bindings/interface/SBSaveCoreOptionsDocstrings.i0
-rw-r--r--lldb/bindings/interfaces.swig2
-rw-r--r--lldb/include/lldb/API/LLDB.h1
-rw-r--r--lldb/include/lldb/API/SBDefines.h1
-rw-r--r--lldb/include/lldb/API/SBError.h1
-rw-r--r--lldb/include/lldb/API/SBFileSpec.h1
-rw-r--r--lldb/include/lldb/API/SBProcess.h6
-rw-r--r--lldb/include/lldb/API/SBSaveCoreOptions.h69
-rw-r--r--lldb/include/lldb/Core/PluginManager.h6
-rw-r--r--lldb/include/lldb/Symbol/SaveCoreOptions.h44
-rw-r--r--lldb/include/lldb/lldb-private-interfaces.h4
-rw-r--r--lldb/source/API/CMakeLists.txt1
-rw-r--r--lldb/source/API/SBProcess.cpp23
-rw-r--r--lldb/source/API/SBSaveCoreOptions.cpp85
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp25
-rw-r--r--lldb/source/Core/PluginManager.cpp46
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp13
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h3
-rw-r--r--lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp16
-rw-r--r--lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h3
-rw-r--r--lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp9
-rw-r--r--lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h3
-rw-r--r--lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp3
-rw-r--r--lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h2
-rw-r--r--lldb/source/Symbol/CMakeLists.txt1
-rw-r--r--lldb/source/Symbol/SaveCoreOptions.cpp53
-rw-r--r--lldb/test/API/functionalities/process_save_core/TestProcessSaveCore.py3
-rw-r--r--lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py21
-rw-r--r--lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py28
-rw-r--r--llvm/docs/CompileCudaWithLLVM.rst2
-rw-r--r--llvm/include/llvm/CodeGen/TargetCallingConv.h8
-rw-r--r--llvm/include/llvm/Object/ArchiveWriter.h11
-rw-r--r--llvm/include/llvm/SandboxIR/Tracker.h41
-rw-r--r--llvm/lib/Analysis/LoopAccessAnalysis.cpp2
-rw-r--r--llvm/lib/IR/Verifier.cpp38
-rw-r--r--llvm/lib/Object/ArchiveWriter.cpp64
-rw-r--r--llvm/lib/SandboxIR/SandboxIR.cpp9
-rw-r--r--llvm/lib/SandboxIR/Tracker.cpp48
-rw-r--r--llvm/lib/Target/AMDGPU/FLATInstructions.td10
-rw-r--r--llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp10
-rw-r--r--llvm/lib/Transforms/Vectorize/LoopVectorize.cpp9
-rw-r--r--llvm/lib/Transforms/Vectorize/VectorCombine.cpp41
-rw-r--r--llvm/test/Instrumentation/MemorySanitizer/AArch64/neon_vst_origins.ll158
-rw-r--r--llvm/test/MC/AArch64/elf-reloc-ptrauth.s18
-rw-r--r--llvm/test/Object/archive-malformed-object.test44
-rw-r--r--llvm/test/Transforms/VectorCombine/RISCV/vecreduce-of-cast.ll30
-rw-r--r--llvm/test/Verifier/byval-size-limit.ll4
-rw-r--r--llvm/test/Verifier/param-align.ll14
-rw-r--r--llvm/test/Verifier/param-attr-align.ll4
-rw-r--r--llvm/test/Verifier/param-ret-align.ll12
-rw-r--r--llvm/unittests/ADT/SetOperationsTest.cpp35
-rw-r--r--llvm/unittests/SandboxIR/TrackerTest.cpp172
-rw-r--r--llvm/utils/gn/secondary/libcxx/include/BUILD.gn2
-rw-r--r--llvm/utils/gn/secondary/lldb/source/API/BUILD.gn1
-rw-r--r--llvm/utils/gn/secondary/lldb/source/Symbol/BUILD.gn1
-rw-r--r--llvm/utils/lit/lit/builtin_commands/cat.py2
-rw-r--r--mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp1
-rw-r--r--utils/bazel/WORKSPACE41
-rw-r--r--utils/bazel/llvm-project-overlay/lldb/BUILD.bazel4
-rw-r--r--utils/bazel/llvm-project-overlay/mlir/BUILD.bazel117
-rw-r--r--utils/bazel/third_party_build/pybind.BUILD15
213 files changed, 5175 insertions, 1369 deletions
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index ea924eb..de9ba09 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -248,7 +248,7 @@ class BinaryContext {
std::shared_ptr<DWARFContext> DWPContext;
/// Decoded pseudo probes.
- std::unique_ptr<MCPseudoProbeDecoder> PseudoProbeDecoder;
+ std::shared_ptr<MCPseudoProbeDecoder> PseudoProbeDecoder;
/// A map of DWO Ids to CUs.
using DWOIdToCUMapType = std::unordered_map<uint64_t, DWARFUnit *>;
@@ -385,11 +385,9 @@ public:
return PseudoProbeDecoder.get();
}
- MCPseudoProbeDecoder &
- setPseudoProbeDecoder(std::unique_ptr<MCPseudoProbeDecoder> Decoder) {
+ void setPseudoProbeDecoder(std::shared_ptr<MCPseudoProbeDecoder> Decoder) {
assert(!PseudoProbeDecoder && "Cannot set pseudo probe decoder twice.");
- PseudoProbeDecoder = std::move(Decoder);
- return *PseudoProbeDecoder.get();
+ PseudoProbeDecoder = Decoder;
}
/// Return BinaryFunction containing a given \p Address or nullptr if
@@ -446,6 +444,9 @@ public:
return nullptr;
}
+ /// Deregister JumpTable registered at a given \p Address and delete it.
+ void deleteJumpTable(uint64_t Address);
+
unsigned getDWARFEncodingSize(unsigned Encoding) {
if (Encoding == dwarf::DW_EH_PE_omit)
return 0;
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index 4bebac3..da3fc43 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -416,9 +416,8 @@ private:
/// different parameters by every pass.
mutable uint64_t Hash{0};
- /// Function GUID assigned by the compiler to the source function.
- /// If non-null, is a valid GUID in pseudo probe section.
- uint64_t PseudoProbeGUID{0};
+ /// Function GUID assigned externally.
+ uint64_t GUID{0};
/// For PLT functions it contains a symbol associated with a function
/// reference. It is nullptr for non-PLT functions.
@@ -2260,10 +2259,10 @@ public:
/// Returns the last computed hash value of the function.
size_t getHash() const { return Hash; }
- /// Returns the function GUID from pseudo-probe description of the function.
- uint64_t getPseudoProbeGUID() const { return PseudoProbeGUID; }
+ /// Returns the function GUID.
+ uint64_t getGUID() const { return GUID; }
- void setPseudoProbeGUID(uint64_t GUID) { PseudoProbeGUID = GUID; }
+ void setGUID(uint64_t Id) { GUID = Id; }
using OperandHashFuncTy =
function_ref<typename std::string(const MCOperand &)>;
diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index c916c6f..32eda0b 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -58,6 +58,8 @@ enum class IndirectBranchType : char {
POSSIBLE_PIC_JUMP_TABLE, /// Possibly a jump table for PIC.
POSSIBLE_GOTO, /// Possibly a gcc's computed goto.
POSSIBLE_FIXED_BRANCH, /// Possibly an indirect branch to a fixed location.
+ POSSIBLE_PIC_FIXED_BRANCH, /// Possibly an indirect jump to a fixed entry in a
+ /// PIC jump table.
};
class MCPlusBuilder {
@@ -1474,12 +1476,11 @@ public:
/// will be set to the different components of the branch. \p MemLocInstr
/// is the instruction that loads up the indirect function pointer. It may
/// or may not be same as \p Instruction.
- virtual IndirectBranchType
- analyzeIndirectBranch(MCInst &Instruction, InstructionIterator Begin,
- InstructionIterator End, const unsigned PtrSize,
- MCInst *&MemLocInstr, unsigned &BaseRegNum,
- unsigned &IndexRegNum, int64_t &DispValue,
- const MCExpr *&DispExpr, MCInst *&PCRelBaseOut) const {
+ virtual IndirectBranchType analyzeIndirectBranch(
+ MCInst &Instruction, InstructionIterator Begin, InstructionIterator End,
+ const unsigned PtrSize, MCInst *&MemLocInstr, unsigned &BaseRegNum,
+ unsigned &IndexRegNum, int64_t &DispValue, const MCExpr *&DispExpr,
+ MCInst *&PCRelBaseOut, MCInst *&FixedEntryLoadInst) const {
llvm_unreachable("not implemented");
return IndirectBranchType::UNKNOWN;
}
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index 0a1f1bb..035f68e 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -2523,6 +2523,16 @@ BinaryFunction *BinaryContext::getBinaryFunctionAtAddress(uint64_t Address) {
return nullptr;
}
+/// Deregister JumpTable registered at a given \p Address and delete it.
+void BinaryContext::deleteJumpTable(uint64_t Address) {
+ assert(JumpTables.count(Address) && "Must have a jump table at address");
+ JumpTable *JT = JumpTables.at(Address);
+ for (BinaryFunction *Parent : JT->Parents)
+ Parent->JumpTables.erase(Address);
+ JumpTables.erase(Address);
+ delete JT;
+}
+
DebugAddressRangesVector BinaryContext::translateModuleAddressRanges(
const DWARFAddressRangesVector &InputRanges) const {
DebugAddressRangesVector OutputRanges;
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 282638f..ea09371 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -780,6 +780,9 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
// setting the value of the register used by the branch.
MCInst *MemLocInstr;
+ // The instruction loading the fixed PIC jump table entry value.
+ MCInst *FixedEntryLoadInstr;
+
// Address of the table referenced by MemLocInstr. Could be either an
// array of function pointers, or a jump table.
uint64_t ArrayStart = 0;
@@ -811,7 +814,7 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
IndirectBranchType BranchType = BC.MIB->analyzeIndirectBranch(
Instruction, Begin, Instructions.end(), PtrSize, MemLocInstr, BaseRegNum,
- IndexRegNum, DispValue, DispExpr, PCRelBaseInstr);
+ IndexRegNum, DispValue, DispExpr, PCRelBaseInstr, FixedEntryLoadInstr);
if (BranchType == IndirectBranchType::UNKNOWN && !MemLocInstr)
return BranchType;
@@ -877,6 +880,43 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
if (BaseRegNum == BC.MRI->getProgramCounter())
ArrayStart += getAddress() + Offset + Size;
+ if (FixedEntryLoadInstr) {
+ assert(BranchType == IndirectBranchType::POSSIBLE_PIC_FIXED_BRANCH &&
+ "Invalid IndirectBranch type");
+ MCInst::iterator FixedEntryDispOperand =
+ BC.MIB->getMemOperandDisp(*FixedEntryLoadInstr);
+ assert(FixedEntryDispOperand != FixedEntryLoadInstr->end() &&
+ "Invalid memory instruction");
+ const MCExpr *FixedEntryDispExpr = FixedEntryDispOperand->getExpr();
+ const uint64_t EntryAddress = getExprValue(FixedEntryDispExpr);
+ uint64_t EntrySize = BC.getJumpTableEntrySize(JumpTable::JTT_PIC);
+ ErrorOr<int64_t> Value =
+ BC.getSignedValueAtAddress(EntryAddress, EntrySize);
+ if (!Value)
+ return IndirectBranchType::UNKNOWN;
+
+ BC.outs() << "BOLT-INFO: fixed PIC indirect branch detected in " << *this
+ << " at 0x" << Twine::utohexstr(getAddress() + Offset)
+ << " referencing data at 0x" << Twine::utohexstr(EntryAddress)
+ << " the destination value is 0x"
+ << Twine::utohexstr(ArrayStart + *Value) << '\n';
+
+ TargetAddress = ArrayStart + *Value;
+
+ // Remove spurious JumpTable at EntryAddress caused by PIC reference from
+ // the load instruction.
+ BC.deleteJumpTable(EntryAddress);
+
+ // Replace FixedEntryDispExpr used in target address calculation with outer
+ // jump table reference.
+ JumpTable *JT = BC.getJumpTableContainingAddress(ArrayStart);
+ assert(JT && "Must have a containing jump table for PIC fixed branch");
+ BC.MIB->replaceMemOperandDisp(*FixedEntryLoadInstr, JT->getFirstLabel(),
+ EntryAddress - ArrayStart, &*BC.Ctx);
+
+ return BranchType;
+ }
+
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: addressed memory is 0x"
<< Twine::utohexstr(ArrayStart) << '\n');
@@ -1126,6 +1166,7 @@ void BinaryFunction::handleIndirectBranch(MCInst &Instruction, uint64_t Size,
}
case IndirectBranchType::POSSIBLE_JUMP_TABLE:
case IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE:
+ case IndirectBranchType::POSSIBLE_PIC_FIXED_BRANCH:
if (opts::JumpTables == JTS_NONE)
IsSimple = false;
break;
@@ -1878,9 +1919,11 @@ bool BinaryFunction::postProcessIndirectBranches(
int64_t DispValue;
const MCExpr *DispExpr;
MCInst *PCRelBaseInstr;
+ MCInst *FixedEntryLoadInstr;
IndirectBranchType Type = BC.MIB->analyzeIndirectBranch(
Instr, BB.begin(), II, PtrSize, MemLocInstr, BaseRegNum,
- IndexRegNum, DispValue, DispExpr, PCRelBaseInstr);
+ IndexRegNum, DispValue, DispExpr, PCRelBaseInstr,
+ FixedEntryLoadInstr);
if (Type != IndirectBranchType::UNKNOWN || MemLocInstr != nullptr)
continue;
diff --git a/bolt/lib/Passes/IndirectCallPromotion.cpp b/bolt/lib/Passes/IndirectCallPromotion.cpp
index a73eb86..2b5a591 100644
--- a/bolt/lib/Passes/IndirectCallPromotion.cpp
+++ b/bolt/lib/Passes/IndirectCallPromotion.cpp
@@ -386,13 +386,15 @@ IndirectCallPromotion::maybeGetHotJumpTableTargets(BinaryBasicBlock &BB,
JumpTableInfoType HotTargets;
MCInst *MemLocInstr;
MCInst *PCRelBaseOut;
+ MCInst *FixedEntryLoadInstr;
unsigned BaseReg, IndexReg;
int64_t DispValue;
const MCExpr *DispExpr;
MutableArrayRef<MCInst> Insts(&BB.front(), &CallInst);
const IndirectBranchType Type = BC.MIB->analyzeIndirectBranch(
CallInst, Insts.begin(), Insts.end(), BC.AsmInfo->getCodePointerSize(),
- MemLocInstr, BaseReg, IndexReg, DispValue, DispExpr, PCRelBaseOut);
+ MemLocInstr, BaseReg, IndexReg, DispValue, DispExpr, PCRelBaseOut,
+ FixedEntryLoadInstr);
assert(MemLocInstr && "There should always be a load for jump tables");
if (!MemLocInstr)
diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp
index beb03a9..fd0a526 100644
--- a/bolt/lib/Profile/DataAggregator.cpp
+++ b/bolt/lib/Profile/DataAggregator.cpp
@@ -2401,7 +2401,7 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
YamlBF.Blocks[BlockIndex].ExecCount += BI.Branches;
}
if (PseudoProbeDecoder) {
- if ((YamlBF.GUID = BF->getPseudoProbeGUID())) {
+ if ((YamlBF.GUID = BF->getGUID())) {
const MCPseudoProbeFuncDesc *FuncDesc =
PseudoProbeDecoder->getFuncDescForGUID(YamlBF.GUID);
YamlBF.PseudoProbeDescHash = FuncDesc->FuncHash;
diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp
index 38345da..82d70e5 100644
--- a/bolt/lib/Profile/YAMLProfileWriter.cpp
+++ b/bolt/lib/Profile/YAMLProfileWriter.cpp
@@ -71,7 +71,7 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS,
YamlBF.NumBasicBlocks = BF.size();
YamlBF.ExecCount = BF.getKnownExecutionCount();
if (PseudoProbeDecoder) {
- if ((YamlBF.GUID = BF.getPseudoProbeGUID())) {
+ if ((YamlBF.GUID = BF.getGUID())) {
const MCPseudoProbeFuncDesc *FuncDesc =
PseudoProbeDecoder->getFuncDescForGUID(YamlBF.GUID);
YamlBF.PseudoProbeDescHash = FuncDesc->FuncHash;
diff --git a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp
index 9249861b..3704a9b 100644
--- a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp
+++ b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/LEB128.h"
+#include <memory>
#undef DEBUG_TYPE
#define DEBUG_TYPE "pseudo-probe-rewriter"
@@ -72,16 +73,19 @@ class PseudoProbeRewriter final : public MetadataRewriter {
void parsePseudoProbe();
/// PseudoProbe decoder
- MCPseudoProbeDecoder &ProbeDecoder;
+ std::shared_ptr<MCPseudoProbeDecoder> ProbeDecoderPtr;
public:
PseudoProbeRewriter(BinaryContext &BC)
: MetadataRewriter("pseudo-probe-rewriter", BC),
- ProbeDecoder(BC.setPseudoProbeDecoder(
- std::make_unique<MCPseudoProbeDecoder>())) {}
+ ProbeDecoderPtr(std::make_shared<MCPseudoProbeDecoder>()) {
+ BC.setPseudoProbeDecoder(ProbeDecoderPtr);
+ }
Error preCFGInitializer() override;
Error postEmitFinalizer() override;
+
+ ~PseudoProbeRewriter() override { ProbeDecoderPtr.reset(); }
};
Error PseudoProbeRewriter::preCFGInitializer() {
@@ -97,6 +101,7 @@ Error PseudoProbeRewriter::postEmitFinalizer() {
}
void PseudoProbeRewriter::parsePseudoProbe() {
+ MCPseudoProbeDecoder &ProbeDecoder(*ProbeDecoderPtr);
PseudoProbeDescSection = BC.getUniqueSectionByName(".pseudo_probe_desc");
PseudoProbeSection = BC.getUniqueSectionByName(".pseudo_probe");
@@ -152,11 +157,12 @@ void PseudoProbeRewriter::parsePseudoProbe() {
continue;
BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncStartAddrs[GUID]);
assert(BF);
- BF->setPseudoProbeGUID(GUID);
+ BF->setGUID(GUID);
}
}
void PseudoProbeRewriter::updatePseudoProbes() {
+ MCPseudoProbeDecoder &ProbeDecoder(*ProbeDecoderPtr);
// check if there is pseudo probe section decoded
if (ProbeDecoder.getAddress2ProbesMap().empty())
return;
@@ -257,6 +263,7 @@ void PseudoProbeRewriter::updatePseudoProbes() {
}
void PseudoProbeRewriter::encodePseudoProbes() {
+ MCPseudoProbeDecoder &ProbeDecoder(*ProbeDecoderPtr);
// Buffer for new pseudo probes section
SmallString<8> Contents;
MCDecodedPseudoProbe *LastProbe = nullptr;
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index 1a2327d..f58f785 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -852,16 +852,19 @@ public:
return Uses;
}
- IndirectBranchType analyzeIndirectBranch(
- MCInst &Instruction, InstructionIterator Begin, InstructionIterator End,
- const unsigned PtrSize, MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut,
- unsigned &IndexRegNumOut, int64_t &DispValueOut,
- const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut) const override {
+ IndirectBranchType
+ analyzeIndirectBranch(MCInst &Instruction, InstructionIterator Begin,
+ InstructionIterator End, const unsigned PtrSize,
+ MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut,
+ unsigned &IndexRegNumOut, int64_t &DispValueOut,
+ const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut,
+ MCInst *&FixedEntryLoadInstr) const override {
MemLocInstrOut = nullptr;
BaseRegNumOut = AArch64::NoRegister;
IndexRegNumOut = AArch64::NoRegister;
DispValueOut = 0;
DispExprOut = nullptr;
+ FixedEntryLoadInstr = nullptr;
// An instruction referencing memory used by jump instruction (directly or
// via register). This location could be an array of function pointers
diff --git a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
index eb3f38a..f8c83b0 100644
--- a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
+++ b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
@@ -176,13 +176,14 @@ public:
MCInst &Instruction, InstructionIterator Begin, InstructionIterator End,
const unsigned PtrSize, MCInst *&MemLocInstr, unsigned &BaseRegNum,
unsigned &IndexRegNum, int64_t &DispValue, const MCExpr *&DispExpr,
- MCInst *&PCRelBaseOut) const override {
+ MCInst *&PCRelBaseOut, MCInst *&FixedEntryLoadInst) const override {
MemLocInstr = nullptr;
BaseRegNum = 0;
IndexRegNum = 0;
DispValue = 0;
DispExpr = nullptr;
PCRelBaseOut = nullptr;
+ FixedEntryLoadInst = nullptr;
// Check for the following long tail call sequence:
// 1: auipc xi, %pcrel_hi(sym)
diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
index e46c425..63086c06 100644
--- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
+++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
@@ -1866,8 +1866,11 @@ public:
return true;
}
+ /// Analyzes PIC-style jump table code template and return identified
+ /// IndirectBranchType, MemLocInstr (all cases) and FixedEntryLoadInstr
+ /// (POSSIBLE_PIC_FIXED_BRANCH case).
template <typename Itr>
- std::pair<IndirectBranchType, MCInst *>
+ std::tuple<IndirectBranchType, MCInst *, MCInst *>
analyzePICJumpTable(Itr II, Itr IE, MCPhysReg R1, MCPhysReg R2) const {
// Analyze PIC-style jump table code template:
//
@@ -1876,6 +1879,13 @@ public:
// add %r2, %r1
// jmp *%r1
//
+ // or a fixed indirect jump template:
+ //
+ // movslq En(%rip), {%r2|%r1} <- FixedEntryLoadInstr
+ // lea PIC_JUMP_TABLE(%rip), {%r1|%r2} <- MemLocInstr
+ // add %r2, %r1
+ // jmp *%r1
+ //
// (with any irrelevant instructions in-between)
//
// When we call this helper we've already determined %r1 and %r2, and
@@ -1916,8 +1926,13 @@ public:
MO.SegRegNum == X86::NoRegister;
};
LLVM_DEBUG(dbgs() << "Checking for PIC jump table\n");
- MCInst *MemLocInstr = nullptr;
- const MCInst *MovInstr = nullptr;
+ MCInst *FirstInstr = nullptr;
+ MCInst *SecondInstr = nullptr;
+ enum {
+ NOMATCH = 0,
+ MATCH_JUMP_TABLE,
+ MATCH_FIXED_BRANCH,
+ } MatchingState = NOMATCH;
while (++II != IE) {
MCInst &Instr = *II;
const MCInstrDesc &InstrDesc = Info->get(Instr.getOpcode());
@@ -1926,68 +1941,76 @@ public:
// Ignore instructions that don't affect R1, R2 registers.
continue;
}
- if (!MovInstr) {
- // Expect to see MOV instruction.
- if (!isMOVSX64rm32(Instr)) {
- LLVM_DEBUG(dbgs() << "MOV instruction expected.\n");
+ const bool IsMOVSXInstr = isMOVSX64rm32(Instr);
+ const bool IsLEAInstr = isLEA64r(Instr);
+ if (MatchingState == NOMATCH) {
+ if (IsMOVSXInstr)
+ MatchingState = MATCH_JUMP_TABLE;
+ else if (IsLEAInstr)
+ MatchingState = MATCH_FIXED_BRANCH;
+ else
break;
- }
- // Check if it's setting %r1 or %r2. In canonical form it sets %r2.
- // If it sets %r1 - rename the registers so we have to only check
- // a single form.
- unsigned MovDestReg = Instr.getOperand(0).getReg();
- if (MovDestReg != R2)
+ // Check if the first instruction is setting %r1 or %r2. In canonical
+ // form lea sets %r1 and mov sets %r2. If it's the opposite - rename so
+ // we have to only check a single form.
+ unsigned DestReg = Instr.getOperand(0).getReg();
+ MCPhysReg &ExpectReg = MatchingState == MATCH_JUMP_TABLE ? R2 : R1;
+ if (DestReg != ExpectReg)
std::swap(R1, R2);
- if (MovDestReg != R2) {
- LLVM_DEBUG(dbgs() << "MOV instruction expected to set %r2\n");
+ if (DestReg != ExpectReg)
break;
- }
- // Verify operands for MOV.
+ // Verify operands
std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Instr);
if (!MO)
break;
- if (!isIndexed(*MO, R1))
- // POSSIBLE_PIC_JUMP_TABLE
+ if ((MatchingState == MATCH_JUMP_TABLE && isIndexed(*MO, R1)) ||
+ (MatchingState == MATCH_FIXED_BRANCH && isRIPRel(*MO)))
+ FirstInstr = &Instr;
+ else
break;
- MovInstr = &Instr;
} else {
- if (!InstrDesc.hasDefOfPhysReg(Instr, R1, *RegInfo))
+ unsigned ExpectReg = MatchingState == MATCH_JUMP_TABLE ? R1 : R2;
+ if (!InstrDesc.hasDefOfPhysReg(Instr, ExpectReg, *RegInfo))
continue;
- if (!isLEA64r(Instr)) {
- LLVM_DEBUG(dbgs() << "LEA instruction expected\n");
+ if ((MatchingState == MATCH_JUMP_TABLE && !IsLEAInstr) ||
+ (MatchingState == MATCH_FIXED_BRANCH && !IsMOVSXInstr))
break;
- }
- if (Instr.getOperand(0).getReg() != R1) {
- LLVM_DEBUG(dbgs() << "LEA instruction expected to set %r1\n");
+ if (Instr.getOperand(0).getReg() != ExpectReg)
break;
- }
- // Verify operands for LEA.
+ // Verify operands.
std::optional<X86MemOperand> MO = evaluateX86MemoryOperand(Instr);
if (!MO)
break;
if (!isRIPRel(*MO))
break;
- MemLocInstr = &Instr;
+ SecondInstr = &Instr;
break;
}
}
- if (!MemLocInstr)
- return std::make_pair(IndirectBranchType::UNKNOWN, nullptr);
+ if (!SecondInstr)
+ return std::make_tuple(IndirectBranchType::UNKNOWN, nullptr, nullptr);
+ if (MatchingState == MATCH_FIXED_BRANCH) {
+ LLVM_DEBUG(dbgs() << "checking potential fixed indirect branch\n");
+ return std::make_tuple(IndirectBranchType::POSSIBLE_PIC_FIXED_BRANCH,
+ FirstInstr, SecondInstr);
+ }
LLVM_DEBUG(dbgs() << "checking potential PIC jump table\n");
- return std::make_pair(IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE,
- MemLocInstr);
+ return std::make_tuple(IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE,
+ SecondInstr, nullptr);
}
- IndirectBranchType analyzeIndirectBranch(
- MCInst &Instruction, InstructionIterator Begin, InstructionIterator End,
- const unsigned PtrSize, MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut,
- unsigned &IndexRegNumOut, int64_t &DispValueOut,
- const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut) const override {
+ IndirectBranchType
+ analyzeIndirectBranch(MCInst &Instruction, InstructionIterator Begin,
+ InstructionIterator End, const unsigned PtrSize,
+ MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut,
+ unsigned &IndexRegNumOut, int64_t &DispValueOut,
+ const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut,
+ MCInst *&FixedEntryLoadInst) const override {
// Try to find a (base) memory location from where the address for
// the indirect branch is loaded. For X86-64 the memory will be specified
// in the following format:
@@ -2014,6 +2037,7 @@ public:
IndexRegNumOut = X86::NoRegister;
DispValueOut = 0;
DispExprOut = nullptr;
+ FixedEntryLoadInst = nullptr;
std::reverse_iterator<InstructionIterator> II(End);
std::reverse_iterator<InstructionIterator> IE(Begin);
@@ -2046,7 +2070,8 @@ public:
unsigned R2 = PrevInstr.getOperand(2).getReg();
if (R1 == R2)
return IndirectBranchType::UNKNOWN;
- std::tie(Type, MemLocInstr) = analyzePICJumpTable(PrevII, IE, R1, R2);
+ std::tie(Type, MemLocInstr, FixedEntryLoadInst) =
+ analyzePICJumpTable(PrevII, IE, R1, R2);
break;
}
return IndirectBranchType::UNKNOWN;
@@ -2090,6 +2115,8 @@ public:
if (MO->ScaleImm != 1 || MO->BaseRegNum != RIPRegister)
return IndirectBranchType::UNKNOWN;
break;
+ case IndirectBranchType::POSSIBLE_PIC_FIXED_BRANCH:
+ break;
default:
if (MO->ScaleImm != PtrSize)
return IndirectBranchType::UNKNOWN;
diff --git a/bolt/test/X86/Inputs/jump-table-fixed-ref-pic.s b/bolt/test/X86/Inputs/jump-table-fixed-ref-pic.s
index 66629a4..6407964 100644
--- a/bolt/test/X86/Inputs/jump-table-fixed-ref-pic.s
+++ b/bolt/test/X86/Inputs/jump-table-fixed-ref-pic.s
@@ -6,7 +6,7 @@ main:
jae .L4
cmpq $0x1, %rdi
jne .L4
- mov .Ljt_pic+8(%rip), %rax
+ movslq .Ljt_pic+8(%rip), %rax
lea .Ljt_pic(%rip), %rdx
add %rdx, %rax
jmpq *%rax
diff --git a/bolt/test/X86/jump-table-fixed-ref-pic.test b/bolt/test/X86/jump-table-fixed-ref-pic.test
index c8b6eda..d215c56 100644
--- a/bolt/test/X86/jump-table-fixed-ref-pic.test
+++ b/bolt/test/X86/jump-table-fixed-ref-pic.test
@@ -1,9 +1,13 @@
## Verify that BOLT detects fixed destination of indirect jump for PIC
## case.
-XFAIL: *
-
RUN: %clang %cflags -no-pie %S/Inputs/jump-table-fixed-ref-pic.s -Wl,-q -o %t
-RUN: llvm-bolt %t --relocs -o %t.null 2>&1 | FileCheck %s
+RUN: llvm-bolt %t --relocs -o %t.null -print-cfg 2>&1 | FileCheck %s
+
+CHECK: BOLT-INFO: fixed PIC indirect branch detected in main {{.*}} the destination value is 0x[[#TGT:]]
+CHECK: Binary Function "main" after building cfg
-CHECK: BOLT-INFO: fixed indirect branch detected in main
+CHECK: movslq ".rodata/1"+8(%rip), %rax
+CHECK-NEXT: leaq ".rodata/1"(%rip), %rdx
+CHECK-NEXT: addq %rdx, %rax
+CHECK-NEXT: jmpq *%rax # UNKNOWN CONTROL FLOW
diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index e62315e..ab29ef3 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -149,12 +149,18 @@ BUILTIN(__builtin_amdgcn_mqsad_pk_u16_u8, "WUiWUiUiWUi", "nc")
BUILTIN(__builtin_amdgcn_mqsad_u32_u8, "V4UiWUiUiV4Ui", "nc")
BUILTIN(__builtin_amdgcn_make_buffer_rsrc, "Qbv*sii", "nc")
-BUILTIN(__builtin_amdgcn_raw_buffer_store_b8, "vcQbiiIi", "n")
-BUILTIN(__builtin_amdgcn_raw_buffer_store_b16, "vsQbiiIi", "n")
-BUILTIN(__builtin_amdgcn_raw_buffer_store_b32, "viQbiiIi", "n")
-BUILTIN(__builtin_amdgcn_raw_buffer_store_b64, "vV2iQbiiIi", "n")
-BUILTIN(__builtin_amdgcn_raw_buffer_store_b96, "vV3iQbiiIi", "n")
-BUILTIN(__builtin_amdgcn_raw_buffer_store_b128, "vV4iQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_store_b8, "vUcQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_store_b16, "vUsQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_store_b32, "vUiQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_store_b64, "vV2UiQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_store_b96, "vV3UiQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_store_b128, "vV4UiQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_load_b8, "UcQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_load_b16, "UsQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_load_b32, "UiQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_load_b64, "V2UiQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_load_b96, "V3UiQbiiIi", "n")
+BUILTIN(__builtin_amdgcn_raw_buffer_load_b128, "V4UiQbiiIi", "n")
//===----------------------------------------------------------------------===//
// Ballot builtins.
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index cfa897f..26a9792 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -156,6 +156,8 @@ def err_drv_unsupported_rtlib_for_platform : Error<
"unsupported runtime library '%0' for platform '%1'">;
def err_drv_invalid_unwindlib_name : Error<
"invalid unwind library name in argument '%0'">;
+def err_drv_unsupported_unwind_for_platform : Error<
+ "unsupported unwind library '%0' for platform '%1'">;
def err_drv_incompatible_unwindlib : Error<
"--rtlib=libgcc requires --unwindlib=libgcc">;
def err_drv_incompatible_options : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 2ad62d6..2d32a85 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -688,7 +688,34 @@ static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD,
const CallExpr *E, llvm::Constant *calleeValue) {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
CGCallee callee = CGCallee::forDirect(calleeValue, GlobalDecl(FD));
- return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
+ RValue Call =
+ CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
+
+ // Check the supported intrinsic.
+ if (unsigned BuiltinID = FD->getBuiltinID()) {
+ auto IsErrnoIntrinsic = [&]() -> unsigned {
+ switch (BuiltinID) {
+ case Builtin::BIexpf:
+ case Builtin::BI__builtin_expf:
+ case Builtin::BI__builtin_expf128:
+ return true;
+ }
+ // TODO: support more FP math libcalls
+ return false;
+ }();
+
+ // Restrict to target with errno, for example, MacOS doesn't set errno.
+ if (IsErrnoIntrinsic && CGF.CGM.getLangOpts().MathErrno &&
+ !CGF.Builder.getIsFPConstrained()) {
+ ASTContext &Context = CGF.getContext();
+ // Emit "int" TBAA metadata on FP math libcalls.
+ clang::QualType IntTy = Context.IntTy;
+ TBAAAccessInfo TBAAInfo = CGF.CGM.getTBAAAccessInfo(IntTy);
+ Instruction *Inst = cast<llvm::Instruction>(Call.getScalarVal());
+ CGF.CGM.DecorateInstructionWithTBAA(Inst, TBAAInfo);
+ }
+ }
+ return Call;
}
/// Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.*
@@ -19185,6 +19212,39 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_raw_buffer_store_b128:
return emitBuiltinWithOneOverloadedType<5>(
*this, E, Intrinsic::amdgcn_raw_ptr_buffer_store);
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b8:
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b16:
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b32:
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b64:
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b96:
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b128: {
+ llvm::Type *RetTy = nullptr;
+ switch (BuiltinID) {
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b8:
+ RetTy = Int8Ty;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b16:
+ RetTy = Int16Ty;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b32:
+ RetTy = Int32Ty;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b64:
+ RetTy = llvm::FixedVectorType::get(Int32Ty, /*NumElements=*/2);
+ break;
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b96:
+ RetTy = llvm::FixedVectorType::get(Int32Ty, /*NumElements=*/3);
+ break;
+ case AMDGPU::BI__builtin_amdgcn_raw_buffer_load_b128:
+ RetTy = llvm::FixedVectorType::get(Int32Ty, /*NumElements=*/4);
+ break;
+ }
+ Function *F =
+ CGM.getIntrinsic(Intrinsic::amdgcn_raw_ptr_buffer_load, RetTy);
+ return Builder.CreateCall(
+ F, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)), EmitScalarExpr(E->getArg(3))});
+ }
default:
return nullptr;
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 6a0af00..c5341e4 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1071,21 +1071,20 @@ using RecIndicesTy =
SmallVector<std::pair<const RecordDecl *, llvm::Value *>, 8>;
static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD,
- const FieldDecl *FD, RecIndicesTy &Indices) {
+ const FieldDecl *Field,
+ RecIndicesTy &Indices) {
const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD);
int64_t FieldNo = -1;
- for (const Decl *D : RD->decls()) {
- if (const auto *Field = dyn_cast<FieldDecl>(D)) {
- FieldNo = Layout.getLLVMFieldNo(Field);
- if (FD == Field) {
- Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
- return true;
- }
+ for (const FieldDecl *FD : RD->fields()) {
+ FieldNo = Layout.getLLVMFieldNo(FD);
+ if (FD == Field) {
+ Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
+ return true;
}
- if (const auto *Record = dyn_cast<RecordDecl>(D)) {
- ++FieldNo;
- if (getGEPIndicesToField(CGF, Record, FD, Indices)) {
+ QualType Ty = FD->getType();
+ if (Ty->isRecordType()) {
+ if (getGEPIndicesToField(CGF, Ty->getAsRecordDecl(), Field, Indices)) {
if (RD->isUnion())
FieldNo = 0;
Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo)));
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 12b3b99..2978139 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -366,11 +366,14 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
options::OPT_t, options::OPT_u_Group});
AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
+ ToolChain::UnwindLibType UNW = HTC.GetUnwindLibType(Args);
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (NeedsSanitizerDeps) {
linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);
- CmdArgs.push_back("-lunwind");
+ if (UNW != ToolChain::UNW_None)
+ CmdArgs.push_back("-lunwind");
}
if (NeedsXRayDeps)
linkXRayRuntimeDeps(HTC, Args, CmdArgs);
@@ -618,13 +621,24 @@ HexagonToolChain::~HexagonToolChain() {}
void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
+ ToolChain::UnwindLibType UNW = GetUnwindLibType(Args);
+ if (UNW != ToolChain::UNW_None && UNW != ToolChain::UNW_CompilerRT) {
+ const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
+ if (A) {
+ getDriver().Diag(diag::err_drv_unsupported_unwind_for_platform)
+ << A->getValue() << getTriple().normalize();
+ return;
+ }
+ }
+
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
- CmdArgs.push_back("-lunwind");
+ if (UNW != ToolChain::UNW_None)
+ CmdArgs.push_back("-lunwind");
break;
case ToolChain::CST_Libstdcxx:
diff --git a/clang/lib/Lex/DependencyDirectivesScanner.cpp b/clang/lib/Lex/DependencyDirectivesScanner.cpp
index 57652be..8a020d0 100644
--- a/clang/lib/Lex/DependencyDirectivesScanner.cpp
+++ b/clang/lib/Lex/DependencyDirectivesScanner.cpp
@@ -660,7 +660,18 @@ bool Scanner::lexModule(const char *&First, const char *const End) {
// an import.
switch (*First) {
- case ':':
+ case ':': {
+ // `module :` is never the start of a valid module declaration.
+ if (Id == "module") {
+ skipLine(First, End);
+ return false;
+ }
+ // `import:(type)name` is a valid ObjC method decl, so check one more token.
+ (void)lexToken(First, End);
+ if (!tryLexIdentifierOrSkipLine(First, End))
+ return false;
+ break;
+ }
case '<':
case '"':
break;
diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c
index 79922eb..32db136 100644
--- a/clang/test/CodeGen/attr-counted-by.c
+++ b/clang/test/CodeGen/attr-counted-by.c
@@ -1852,3 +1852,57 @@ struct annotated_struct_array {
void test29(struct annotated_struct_array *ann, int idx1, int idx2) {
ann->ann_array[idx1]->array[idx2] = __builtin_dynamic_object_size(ann->ann_array[idx1]->array, 1);
}
+
+typedef struct {
+ char __padding[0];
+} test30_spinlock_t;
+
+struct test30_struct {
+ struct test30_decl *name_node;
+ int priv_len;
+ test30_spinlock_t pcpu_refcnt;
+ char priv[] __counted_by(priv_len);
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test30(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR5]] {
+// SANITIZE-WITH-ATTR-NEXT: entry:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META2]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB39:[0-9]+]], i64 [[TMP0]]) #[[ATTR10]], !nosanitize [[META2]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test30(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: entry:
+// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 4)
+// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], 12
+// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i8 0, i8 [[TMP2]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[PCPU_REFCNT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 12
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[PCPU_REFCNT]], i64 0, i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test30(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR3]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: entry:
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[IDX]] to i64, !nosanitize [[META9]]
+// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP0]]) #[[ATTR8]], !nosanitize [[META9]]
+// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test30(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[PCPU_REFCNT:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 12
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[PCPU_REFCNT]], i64 0, i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test30(struct test30_struct *ptr, int idx) {
+ ptr->pcpu_refcnt.__padding[idx] = __builtin_dynamic_object_size(ptr, 1);
+}
diff --git a/clang/test/CodeGen/math-libcalls-tbaa.cpp b/clang/test/CodeGen/math-libcalls-tbaa.cpp
index 0b231d4..f15938d 100644
--- a/clang/test/CodeGen/math-libcalls-tbaa.cpp
+++ b/clang/test/CodeGen/math-libcalls-tbaa.cpp
@@ -12,9 +12,8 @@ extern "C" float expf(float);
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 40
// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call float @expf(float noundef [[TMP0]]) #[[ATTR2:[0-9]+]]
-// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
-// CHECK-NEXT: [[MUL:%.*]] = fmul float [[CALL]], [[TMP1]]
+// CHECK-NEXT: [[CALL:%.*]] = tail call float @expf(float noundef [[TMP0]]) #[[ATTR2:[0-9]+]], !tbaa [[TBAA6:![0-9]+]]
+// CHECK-NEXT: [[MUL:%.*]] = fmul float [[TMP0]], [[CALL]]
// CHECK-NEXT: ret float [[MUL]]
//
extern "C" float foo (float num[], float r2inv, int n) {
@@ -27,11 +26,15 @@ extern "C" float foo (float num[], float r2inv, int n) {
// NoNewStructPathTBAA: [[META3]] = !{!"float", [[META4:![0-9]+]], i64 0}
// NoNewStructPathTBAA: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// NoNewStructPathTBAA: [[META5]] = !{!"Simple C++ TBAA"}
+// NoNewStructPathTBAA: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
+// NoNewStructPathTBAA: [[META7]] = !{!"int", [[META4]], i64 0}
//.
// NewStructPathTBAA: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0, i64 4}
// NewStructPathTBAA: [[META3]] = !{[[META4:![0-9]+]], i64 4, !"float"}
// NewStructPathTBAA: [[META4]] = !{[[META5:![0-9]+]], i64 1, !"omnipotent char"}
// NewStructPathTBAA: [[META5]] = !{!"Simple C++ TBAA"}
+// NewStructPathTBAA: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0, i64 4}
+// NewStructPathTBAA: [[META7]] = !{[[META4]], i64 4, !"int"}
//.
//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
// NewStructPathTBAA: {{.*}}
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load.cl
new file mode 100644
index 0000000..3403b69
--- /dev/null
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-load.cl
@@ -0,0 +1,172 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu verde -emit-llvm -o - %s | FileCheck %s
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned int v2u32 __attribute__((ext_vector_type(2)));
+typedef unsigned int v3u32 __attribute__((ext_vector_type(3)));
+typedef unsigned int v4u32 __attribute__((ext_vector_type(4)));
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b8(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.amdgcn.raw.ptr.buffer.load.i8(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
+// CHECK-NEXT: ret i8 [[TMP0]]
+//
+u8 test_amdgcn_raw_ptr_buffer_load_b8(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b8(rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b16(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.amdgcn.raw.ptr.buffer.load.i16(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
+// CHECK-NEXT: ret i16 [[TMP0]]
+//
+u16 test_amdgcn_raw_ptr_buffer_load_b16(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b16(rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b32(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
+// CHECK-NEXT: ret i32 [[TMP0]]
+//
+u32 test_amdgcn_raw_ptr_buffer_load_b32(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b32(rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b64(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v2i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
+// CHECK-NEXT: ret <2 x i32> [[TMP0]]
+//
+v2u32 test_amdgcn_raw_ptr_buffer_load_b64(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b64(rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b96(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <3 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v3i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
+// CHECK-NEXT: ret <3 x i32> [[TMP0]]
+//
+v3u32 test_amdgcn_raw_ptr_buffer_load_b96(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b96(rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b128(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v4i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
+// CHECK-NEXT: ret <4 x i32> [[TMP0]]
+//
+v4u32 test_amdgcn_raw_ptr_buffer_load_b128(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b128(rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b8_non_const_offset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.amdgcn.raw.ptr.buffer.load.i8(ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
+// CHECK-NEXT: ret i8 [[TMP0]]
+//
+u8 test_amdgcn_raw_ptr_buffer_load_b8_non_const_offset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b8(rsrc, offset, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b16_non_const_offset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.amdgcn.raw.ptr.buffer.load.i16(ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
+// CHECK-NEXT: ret i16 [[TMP0]]
+//
+u16 test_amdgcn_raw_ptr_buffer_load_b16_non_const_offset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b16(rsrc, offset, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b32_non_const_offset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
+// CHECK-NEXT: ret i32 [[TMP0]]
+//
+u32 test_amdgcn_raw_ptr_buffer_load_b32_non_const_offset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b32(rsrc, offset, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b64_non_const_offset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v2i32(ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
+// CHECK-NEXT: ret <2 x i32> [[TMP0]]
+//
+v2u32 test_amdgcn_raw_ptr_buffer_load_b64_non_const_offset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b64(rsrc, offset, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b96_non_const_offset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <3 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v3i32(ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
+// CHECK-NEXT: ret <3 x i32> [[TMP0]]
+//
+v3u32 test_amdgcn_raw_ptr_buffer_load_b96_non_const_offset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b96(rsrc, offset, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b128_non_const_offset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v4i32(ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
+// CHECK-NEXT: ret <4 x i32> [[TMP0]]
+//
+v4u32 test_amdgcn_raw_ptr_buffer_load_b128_non_const_offset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b128(rsrc, offset, /*soffset=*/0, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b8_non_const_soffset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.amdgcn.raw.ptr.buffer.load.i8(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
+// CHECK-NEXT: ret i8 [[TMP0]]
+//
+u8 test_amdgcn_raw_ptr_buffer_load_b8_non_const_soffset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b8(rsrc, /*offset=*/0, soffset, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b16_non_const_soffset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.amdgcn.raw.ptr.buffer.load.i16(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
+// CHECK-NEXT: ret i16 [[TMP0]]
+//
+u16 test_amdgcn_raw_ptr_buffer_load_b16_non_const_soffset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b16(rsrc, /*offset=*/0, soffset, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b32_non_const_soffset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
+// CHECK-NEXT: ret i32 [[TMP0]]
+//
+u32 test_amdgcn_raw_ptr_buffer_load_b32_non_const_soffset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b32(rsrc, /*offset=*/0, soffset, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b64_non_const_soffset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v2i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
+// CHECK-NEXT: ret <2 x i32> [[TMP0]]
+//
+v2u32 test_amdgcn_raw_ptr_buffer_load_b64_non_const_soffset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b64(rsrc, /*offset=*/0, soffset, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b96_non_const_soffset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <3 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v3i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
+// CHECK-NEXT: ret <3 x i32> [[TMP0]]
+//
+v3u32 test_amdgcn_raw_ptr_buffer_load_b96_non_const_soffset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b96(rsrc, /*offset=*/0, soffset, /*aux=*/0);
+}
+
+// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_load_b128_non_const_soffset(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.amdgcn.raw.ptr.buffer.load.v4i32(ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
+// CHECK-NEXT: ret <4 x i32> [[TMP0]]
+//
+v4u32 test_amdgcn_raw_ptr_buffer_load_b128_non_const_soffset(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+ return __builtin_amdgcn_raw_buffer_load_b128(rsrc, /*offset=*/0, soffset, /*aux=*/0);
+}
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-store.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-store.cl
index 37975d5..097c545 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-store.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-raw-buffer-store.cl
@@ -2,19 +2,19 @@
// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu verde -emit-llvm -o - %s | FileCheck %s
-typedef char i8;
-typedef short i16;
-typedef int i32;
-typedef int i64 __attribute__((ext_vector_type(2)));
-typedef int i96 __attribute__((ext_vector_type(3)));
-typedef int i128 __attribute__((ext_vector_type(4)));
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned int v2u32 __attribute__((ext_vector_type(2)));
+typedef unsigned int v3u32 __attribute__((ext_vector_type(3)));
+typedef unsigned int v4u32 __attribute__((ext_vector_type(4)));
// CHECK-LABEL: @test_amdgcn_raw_ptr_buffer_store_b8(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i8(i8 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b8(i8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b8(u8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b8(vdata, rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
}
@@ -23,7 +23,7 @@ void test_amdgcn_raw_ptr_buffer_store_b8(i8 vdata, __amdgpu_buffer_rsrc_t rsrc,
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i16(i16 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b16(i16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b16(u16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b16(vdata, rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
}
@@ -32,7 +32,7 @@ void test_amdgcn_raw_ptr_buffer_store_b16(i16 vdata, __amdgpu_buffer_rsrc_t rsrc
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b32(i32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b32(u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b32(vdata, rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
}
@@ -41,7 +41,7 @@ void test_amdgcn_raw_ptr_buffer_store_b32(i32 vdata, __amdgpu_buffer_rsrc_t rsrc
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v2i32(<2 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b64(i64 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b64(v2u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b64(vdata, rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
}
@@ -50,7 +50,7 @@ void test_amdgcn_raw_ptr_buffer_store_b64(i64 vdata, __amdgpu_buffer_rsrc_t rsrc
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v3i32(<3 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b96(i96 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b96(v3u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b96(vdata, rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
}
@@ -59,7 +59,7 @@ void test_amdgcn_raw_ptr_buffer_store_b96(i96 vdata, __amdgpu_buffer_rsrc_t rsrc
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v4i32(<4 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b128(i128 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b128(v4u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b128(vdata, rsrc, /*offset=*/0, /*soffset=*/0, /*aux=*/0);
}
@@ -68,7 +68,7 @@ void test_amdgcn_raw_ptr_buffer_store_b128(i128 vdata, __amdgpu_buffer_rsrc_t rs
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i8(i8 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b8_non_const_offset(i8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b8_non_const_offset(u8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b8(vdata, rsrc, offset, /*soffset=*/0, /*aux=*/0);
}
@@ -77,7 +77,7 @@ void test_amdgcn_raw_ptr_buffer_store_b8_non_const_offset(i8 vdata, __amdgpu_buf
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i16(i16 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b16_non_const_offset(i16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b16_non_const_offset(u16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b16(vdata, rsrc, offset, /*soffset=*/0, /*aux=*/0);
}
@@ -86,7 +86,7 @@ void test_amdgcn_raw_ptr_buffer_store_b16_non_const_offset(i16 vdata, __amdgpu_b
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b32_non_const_offset(i32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b32_non_const_offset(u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b32(vdata, rsrc, offset, /*soffset=*/0, /*aux=*/0);
}
@@ -95,7 +95,7 @@ void test_amdgcn_raw_ptr_buffer_store_b32_non_const_offset(i32 vdata, __amdgpu_b
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v2i32(<2 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b64_non_const_offset(i64 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b64_non_const_offset(v2u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b64(vdata, rsrc, offset, /*soffset=*/0, /*aux=*/0);
}
@@ -104,7 +104,7 @@ void test_amdgcn_raw_ptr_buffer_store_b64_non_const_offset(i64 vdata, __amdgpu_b
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v3i32(<3 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b96_non_const_offset(i96 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b96_non_const_offset(v3u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b96(vdata, rsrc, offset, /*soffset=*/0, /*aux=*/0);
}
@@ -113,7 +113,7 @@ void test_amdgcn_raw_ptr_buffer_store_b96_non_const_offset(i96 vdata, __amdgpu_b
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v4i32(<4 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 [[OFFSET:%.*]], i32 0, i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b128_non_const_offset(i128 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b128_non_const_offset(v4u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b128(vdata, rsrc, offset, /*soffset=*/0, /*aux=*/0);
}
@@ -122,7 +122,7 @@ void test_amdgcn_raw_ptr_buffer_store_b128_non_const_offset(i128 vdata, __amdgpu
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i8(i8 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b8_non_const_soffset(i8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b8_non_const_soffset(u8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b8(vdata, rsrc, /*offset=*/0, soffset, /*aux=*/0);
}
@@ -131,7 +131,7 @@ void test_amdgcn_raw_ptr_buffer_store_b8_non_const_soffset(i8 vdata, __amdgpu_bu
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i16(i16 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b16_non_const_soffset(i16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b16_non_const_soffset(u16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b16(vdata, rsrc, /*offset=*/0, soffset, /*aux=*/0);
}
@@ -140,7 +140,7 @@ void test_amdgcn_raw_ptr_buffer_store_b16_non_const_soffset(i16 vdata, __amdgpu_
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b32_non_const_soffset(i32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b32_non_const_soffset(u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b32(vdata, rsrc, /*offset=*/0, soffset, /*aux=*/0);
}
@@ -149,7 +149,7 @@ void test_amdgcn_raw_ptr_buffer_store_b32_non_const_soffset(i32 vdata, __amdgpu_
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v2i32(<2 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b64_non_const_soffset(i64 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b64_non_const_soffset(v2u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b64(vdata, rsrc, /*offset=*/0, soffset, /*aux=*/0);
}
@@ -158,7 +158,7 @@ void test_amdgcn_raw_ptr_buffer_store_b64_non_const_soffset(i64 vdata, __amdgpu_
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v3i32(<3 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b96_non_const_soffset(i96 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b96_non_const_soffset(v3u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b96(vdata, rsrc, /*offset=*/0, soffset, /*aux=*/0);
}
@@ -167,6 +167,6 @@ void test_amdgcn_raw_ptr_buffer_store_b96_non_const_soffset(i96 vdata, __amdgpu_
// CHECK-NEXT: tail call void @llvm.amdgcn.raw.ptr.buffer.store.v4i32(<4 x i32> [[VDATA:%.*]], ptr addrspace(8) [[RSRC:%.*]], i32 0, i32 [[SOFFSET:%.*]], i32 0)
// CHECK-NEXT: ret void
//
-void test_amdgcn_raw_ptr_buffer_store_b128_non_const_soffset(i128 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
+void test_amdgcn_raw_ptr_buffer_store_b128_non_const_soffset(v4u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset) {
__builtin_amdgcn_raw_buffer_store_b128(vdata, rsrc, /*offset=*/0, soffset, /*aux=*/0);
}
diff --git a/clang/test/Driver/hexagon-toolchain-linux.c b/clang/test/Driver/hexagon-toolchain-linux.c
index fe32638..86cc9a3 100644
--- a/clang/test/Driver/hexagon-toolchain-linux.c
+++ b/clang/test/Driver/hexagon-toolchain-linux.c
@@ -119,3 +119,36 @@
// CHECK010: crt1.o
// CHECK010: "-L/tmp"
// CHECK010-NOT: "-lstandalone"
+
+// -----------------------------------------------------------------------------
+// unwindlib
+// -----------------------------------------------------------------------------
+// RUN: %clangxx --unwindlib=none \
+// RUN: --target=hexagon-unknown-linux-musl %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK011 %s
+// CHECK011: InstalledDir: [[INSTALLED_DIR:.+]]
+// CHECK011: crt1.o
+// CHECK011-NOT: "-lunwind"
+// CHECK011-NOT: "-lgcc_eh"
+// CHECK012-NOT: "-lgcc_s"
+
+
+// RUN: %clangxx --rtlib=compiler-rt --unwindlib=libunwind \
+// RUN: --target=hexagon-unknown-linux-musl %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK012 %s
+// RUN: %clangxx \
+// RUN: --target=hexagon-unknown-linux-musl %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK012 %s
+// CHECK012: InstalledDir: [[INSTALLED_DIR:.+]]
+// CHECK012: crt1.o
+// CHECK012: "-lunwind"
+// CHECK012-NOT: "-lgcc_eh"
+// CHECK012-NOT: "-lgcc_s"
+
+// RUN: not %clangxx --rtlib=compiler-rt --unwindlib=libgcc \
+// RUN: --target=hexagon-unknown-linux-musl %s -### 2>&1 \
+// RUN: | FileCheck -check-prefix=CHECK013 %s
+// CHECK013: error: unsupported unwind library 'libgcc' for platform 'hexagon-unknown-linux-musl'
+// CHECK013-NOT: "-lgcc_eh"
+// CHECK013-NOT: "-lgcc_s"
+// CHECK013-NOT: "-lunwind"
diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c
index d811cb3..71cc36a 100644
--- a/clang/test/Preprocessor/aarch64-target-features.c
+++ b/clang/test/Preprocessor/aarch64-target-features.c
@@ -291,309 +291,54 @@
// RUN: %clang -target aarch64 -mtune=CYCLONE -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MTUNE-CYCLONE %s
// CHECK-MTUNE-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8a"
-// RUN: %clang -target aarch64 -mcpu=apple-a7 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
-// RUN: %clang -target aarch64 -mcpu=apple-a8 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
-// RUN: %clang -target aarch64 -mcpu=apple-a9 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
-// RUN: %clang -target aarch64 -mcpu=apple-a10 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A10 %s
-// RUN: %clang -target aarch64 -mcpu=apple-a11 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A11 %s
-// RUN: %clang -target aarch64 -mcpu=apple-a12 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s
-// RUN: %clang -target aarch64 -mcpu=apple-a13 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A13 %s
-// RUN: %clang -target aarch64 -mcpu=apple-s4 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s
-// RUN: %clang -target aarch64 -mcpu=apple-s5 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s
-// RUN: %clang -target aarch64 -mcpu=cyclone -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
-// RUN: %clang -target aarch64 -mcpu=cortex-a34 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-A34 %s
-// RUN: %clang -target aarch64 -mcpu=cortex-a35 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-A35 %s
-// RUN: %clang -target aarch64 -mcpu=cortex-a53 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-A53 %s
-// RUN: %clang -target aarch64 -mcpu=cortex-a57 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-A57 %s
-// RUN: %clang -target aarch64 -mcpu=cortex-a72 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-A72 %s
-// RUN: %clang -target aarch64 -mcpu=cortex-a73 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-CORTEX-A73 %s
-// RUN: %clang -target aarch64 -mcpu=cortex-r82 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-CORTEX-R82 %s
-// RUN: %clang -target aarch64 -mcpu=exynos-m3 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-M3 %s
-// RUN: %clang -target aarch64 -mcpu=exynos-m4 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-M4 %s
-// RUN: %clang -target aarch64 -mcpu=exynos-m5 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-M4 %s
-// RUN: %clang -target aarch64 -mcpu=kryo -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-KRYO %s
-// RUN: %clang -target aarch64 -mcpu=thunderx2t99 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-THUNDERX2T99 %s
-// RUN: %clang -target aarch64 -mcpu=a64fx -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-A64FX %s
-// RUN: %clang -target aarch64 -mcpu=carmel -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck -check-prefix=CHECK-MCPU-CARMEL %s
-// CHECK-MCPU-APPLE-A7-LABEL: "-target-cpu" "apple-a7"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+zcm"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+zcz"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-APPLE-A7-NEXT: "-target-abi"
-// CHECK-MCPU-APPLE-A10-LABEL: "-target-cpu" "apple-a10"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+zcm"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+zcz"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+lor"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+pan"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-feature" "+vh"
-// CHECK-MCPU-APPLE-A10-NEXT: "-target-abi"
-// CHECK-MCPU-APPLE-A11-LABEL: "-target-cpu" "apple-a11"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+zcm"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+zcz"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+v8.2a"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+fullfp16"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+ras"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-APPLE-A11-NEXT: "-target-abi"
-// CHECK-MCPU-APPLE-A12-LABEL: "-target-cpu" "apple-a12"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+zcm"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+zcz"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+v8.3a"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+complxnum"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+fullfp16"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+jsconv"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+pauth"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+ras"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+rcpc"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-APPLE-A12-NEXT: "-target-abi"
-// CHECK-MCPU-A34-LABEL: "-target-cpu" "cortex-a34"
-// CHECK-MCPU-A34-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-A34-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-A34-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-A34-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-A34-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-A34-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-A34-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-A34-NEXT: "-target-abi"
-// CHECK-MCPU-APPLE-A13-LABEL: "-target-cpu" "apple-a13"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+zcm"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+zcz"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+v8.4a"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+complxnum"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+dotprod"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+fp16fml"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+fullfp16"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+jsconv"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+pauth"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+ras"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+rcpc"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-feature" "+sha3"
-// CHECK-MCPU-APPLE-A13-NEXT: "-target-abi"
-// CHECK-MCPU-A35-LABEL: "-target-cpu" "cortex-a35"
-// CHECK-MCPU-A35-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-A35-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-A35-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-A35-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-A35-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-A35-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-A35-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-A35-NEXT: "-target-abi"
-// CHECK-MCPU-A53-LABEL: "-target-cpu" "cortex-a53"
-// CHECK-MCPU-A53-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-A53-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-A53-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-A53-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-A53-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-A53-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-A53-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-A53-NEXT: "-target-abi"
-// CHECK-MCPU-A57-LABEL: "-target-cpu" "cortex-a57"
-// CHECK-MCPU-A57-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-A57-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-A57-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-A57-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-A57-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-A57-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-A57-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-A57-NEXT: "-target-abi"
-// CHECK-MCPU-A72-LABEL: "-target-cpu" "cortex-a72"
-// CHECK-MCPU-A72-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-A72-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-A72-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-A72-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-A72-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-A72-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-A72-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-A72-NEXT: "-target-abi"
-// CHECK-MCPU-CORTEX-A73-LABEL: "-target-cpu" "cortex-a73"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-CORTEX-A73-NEXT: "-target-abi"
-// CHECK-MCPU-CORTEX-R82-LABEL: "-target-cpu" "cortex-r82"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+v8r"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+ccdp"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+complxnum"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+dotprod"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+flagm"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+fp16fml"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+fullfp16"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+jsconv"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+pauth"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+predres"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+ras"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+rcpc"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+sb"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-feature" "+ssbs"
-// CHECK-MCPU-CORTEX-R82-NEXT: "-target-abi"
-// CHECK-MCPU-M3-LABEL: "-target-cpu" "exynos-m3"
-// CHECK-MCPU-M3-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-M3-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-M3-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-M3-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-M3-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-M3-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-M3-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-M3-NEXT: "-target-abi"
-// CHECK-MCPU-M4-LABEL: "-target-cpu" "exynos-m{{[45]}}"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+v8.2a"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+dotprod"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+fullfp16"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+ras"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-M4-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-M4-NEXT: "-target-abi"
-// CHECK-MCPU-KRYO-LABEL: "-target-cpu" "kryo"
-// CHECK-MCPU-KRYO-NEXT: "-target-feature" "+v8a"
-// CHECK-MCPU-KRYO-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-KRYO-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-KRYO-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-KRYO-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-KRYO-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-KRYO-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-KRYO-NEXT: "-target-abi"
-// CHECK-MCPU-THUNDERX2T99-LABEL: "-target-cpu" "thunderx2t99"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+v8.1a"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-feature" "+sha2
-// CHECK-MCPU-THUNDERX2T99-NEXT: "-target-abi"
-// CHECK-MCPU-A64FX-LABEL: "-target-cpu" "a64fx"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+v8.2a"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+complxnum"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+fullfp16"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+perfmon"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+ras"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-A64FX-NEXT: "-target-feature" "+sve"
-// CHECK-MCPU-A64FX-NEXT: "-target-abi"
-// CHECK-MCPU-CARMEL-LABEL: "-target-cpu" "carmel"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+v8.2a"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+aes"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+crc"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+fullfp16"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+lse"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+neon"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+ras"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+rdm"
-// CHECK-MCPU-CARMEL-NEXT: "-target-feature" "+sha2"
-// CHECK-MCPU-CARMEL-NEXT: "-target-abi"
-
-
-// RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s
-// CHECK-ARCH-ARM64-LABEL: "-target-cpu" "apple-m1"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+zcm"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+zcz"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+v8.4a"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+aes"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+altnzcv"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+ccdp"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+complxnum"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+crc"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+dotprod"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+fp16fml"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+fptoint"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+fullfp16"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+jsconv"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+lse"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+neon"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+pauth"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+perfmon"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+predres"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+ras"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+rcpc"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+rdm"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+sb"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+sha2"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+sha3"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+specrestrict"
-// CHECK-ARCH-ARM64-NEXT: "-target-feature" "+ssbs"
-// CHECK-ARCH-ARM64-NEXT: "-target-abi"
-
-// RUN: %clang -target x86_64-apple-macosx -arch arm64_32 -### -c %s 2>&1 | sed -e 's/"-/\n"-/g' | FileCheck --check-prefix=CHECK-ARCH-ARM64_32 %s
-// CHECK-ARCH-ARM64_32-LABEL: "-target-cpu" "apple-s4"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+zcm"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+zcz"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+v8.3a"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+aes"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+complxnum"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+crc"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+fp-armv8"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+fullfp16"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+jsconv"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+lse"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+neon"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+pauth"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+perfmon"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+ras"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+rcpc"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+rdm"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-feature" "+sha2"
-// CHECK-ARCH-ARM64_32-NEXT: "-target-abi"
+// RUN: %clang -target aarch64 -mcpu=apple-a7 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
+// RUN: %clang -target aarch64 -mcpu=apple-a8 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
+// RUN: %clang -target aarch64 -mcpu=apple-a9 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
+// RUN: %clang -target aarch64 -mcpu=apple-a10 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A10 %s
+// RUN: %clang -target aarch64 -mcpu=apple-a11 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A11 %s
+// RUN: %clang -target aarch64 -mcpu=apple-a12 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s
+// RUN: %clang -target aarch64 -mcpu=apple-a13 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A13 %s
+// RUN: %clang -target aarch64 -mcpu=apple-s4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s
+// RUN: %clang -target aarch64 -mcpu=apple-s5 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A12 %s
+// RUN: %clang -target aarch64 -mcpu=cyclone -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-APPLE-A7 %s
+// RUN: %clang -target aarch64 -mcpu=cortex-a34 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A34 %s
+// RUN: %clang -target aarch64 -mcpu=cortex-a35 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A35 %s
+// RUN: %clang -target aarch64 -mcpu=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A53 %s
+// RUN: %clang -target aarch64 -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A57 %s
+// RUN: %clang -target aarch64 -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A72 %s
+// RUN: %clang -target aarch64 -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-CORTEX-A73 %s
+// RUN: %clang -target aarch64 -mcpu=cortex-r82 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-CORTEX-R82 %s
+// RUN: %clang -target aarch64 -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M3 %s
+// RUN: %clang -target aarch64 -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M4 %s
+// RUN: %clang -target aarch64 -mcpu=exynos-m5 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M4 %s
+// RUN: %clang -target aarch64 -mcpu=kryo -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-KRYO %s
+// RUN: %clang -target aarch64 -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-THUNDERX2T99 %s
+// RUN: %clang -target aarch64 -mcpu=a64fx -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A64FX %s
+// RUN: %clang -target aarch64 -mcpu=carmel -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-CARMEL %s
+// CHECK-MCPU-APPLE-A7: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-APPLE-A10: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+lor" "-target-feature" "+neon" "-target-feature" "+pan" "-target-feature" "+perfmon" "-target-feature" "+rdm" "-target-feature" "+sha2" "-target-feature" "+vh"
+// CHECK-MCPU-APPLE-A11: "-cc1"{{.*}} "-triple" "aarch64{{.*}}"{{.*}}"-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2"
+// CHECK-MCPU-APPLE-A12: "-cc1"{{.*}} "-triple" "aarch64"{{.*}} "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.3a" "-target-feature" "+aes" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sha2"
+// CHECK-MCPU-A34: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-APPLE-A13: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.4a" "-target-feature" "+aes" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sha2" "-target-feature" "+sha3"
+// CHECK-MCPU-A35: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-A53: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-A57: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-A72: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-CORTEX-A73: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-CORTEX-R82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8r" "-target-feature" "+ccdp" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+flagm" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+predres" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sb" "-target-feature" "+ssbs"
+// CHECK-MCPU-M3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-M4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2"
+// CHECK-MCPU-KRYO: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2"
+// CHECK-MCPU-THUNDERX2T99: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.1a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+rdm" "-target-feature" "+sha2
+// CHECK-MCPU-A64FX: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2" "-target-feature" "+sve"
+// CHECK-MCPU-CARMEL: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2"
+
+// RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s
+// CHECK-ARCH-ARM64: "-target-cpu" "apple-m1" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.4a" "-target-feature" "+aes" "-target-feature" "+altnzcv" "-target-feature" "+ccdp" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+fptoint" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+predres" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sb" "-target-feature" "+sha2" "-target-feature" "+sha3" "-target-feature" "+specrestrict" "-target-feature" "+ssbs"
+
+// RUN: %clang -target x86_64-apple-macosx -arch arm64_32 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64_32 %s
+// CHECK-ARCH-ARM64_32: "-target-cpu" "apple-s4" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.3a" "-target-feature" "+aes" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sha2"
// RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s
// RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s
diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-load-error.cl b/clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-load-error.cl
new file mode 100644
index 0000000..5d123c8
--- /dev/null
+++ b/clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-load-error.cl
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu verde -S -verify -o - %s
+// REQUIRES: amdgpu-registered-target
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned int v2u32 __attribute__((ext_vector_type(2)));
+typedef unsigned int v3u32 __attribute__((ext_vector_type(3)));
+typedef unsigned int v4u32 __attribute__((ext_vector_type(4)));
+
+u8 test_amdgcn_raw_ptr_buffer_load_b8(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+ return __builtin_amdgcn_raw_buffer_load_b8(rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_load_b8' must be a constant integer}}
+}
+
+u16 test_amdgcn_raw_ptr_buffer_load_b16(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+ return __builtin_amdgcn_raw_buffer_load_b16(rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_load_b16' must be a constant integer}}
+}
+
+u32 test_amdgcn_raw_ptr_buffer_load_b32(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+ return __builtin_amdgcn_raw_buffer_load_b32(rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_load_b32' must be a constant integer}}
+}
+
+v2u32 test_amdgcn_raw_ptr_buffer_load_b64(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+ return __builtin_amdgcn_raw_buffer_load_b64(rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_load_b64' must be a constant integer}}
+}
+
+v3u32 test_amdgcn_raw_ptr_buffer_load_b96(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+ return __builtin_amdgcn_raw_buffer_load_b96(rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_load_b96' must be a constant integer}}
+}
+
+v4u32 test_amdgcn_raw_ptr_buffer_load_b128(__amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+ return __builtin_amdgcn_raw_buffer_load_b128(rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_load_b128' must be a constant integer}}
+}
diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-store-error.cl b/clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-store-error.cl
index 356c031..119adcd 100644
--- a/clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-store-error.cl
+++ b/clang/test/SemaOpenCL/builtins-amdgcn-raw-buffer-store-error.cl
@@ -3,33 +3,33 @@
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
-typedef char i8;
-typedef short i16;
-typedef int i32;
-typedef int i64 __attribute__((ext_vector_type(2)));
-typedef int i96 __attribute__((ext_vector_type(3)));
-typedef int i128 __attribute__((ext_vector_type(4)));
-
-void test_amdgcn_raw_ptr_buffer_store_b8(i8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned int v2u32 __attribute__((ext_vector_type(2)));
+typedef unsigned int v3u32 __attribute__((ext_vector_type(3)));
+typedef unsigned int v4u32 __attribute__((ext_vector_type(4)));
+
+void test_amdgcn_raw_ptr_buffer_store_b8(u8 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
__builtin_amdgcn_raw_buffer_store_b8(vdata, rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_store_b8' must be a constant integer}}
}
-void test_amdgcn_raw_ptr_buffer_store_b16(i16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+void test_amdgcn_raw_ptr_buffer_store_b16(u16 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
__builtin_amdgcn_raw_buffer_store_b16(vdata, rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_store_b16' must be a constant integer}}
}
-void test_amdgcn_raw_ptr_buffer_store_b32(i32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+void test_amdgcn_raw_ptr_buffer_store_b32(u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
__builtin_amdgcn_raw_buffer_store_b32(vdata, rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_store_b32' must be a constant integer}}
}
-void test_amdgcn_raw_ptr_buffer_store_b64(i64 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+void test_amdgcn_raw_ptr_buffer_store_b64(v2u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
__builtin_amdgcn_raw_buffer_store_b64(vdata, rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_store_b64' must be a constant integer}}
}
-void test_amdgcn_raw_ptr_buffer_store_b96(i96 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+void test_amdgcn_raw_ptr_buffer_store_b96(v3u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
__builtin_amdgcn_raw_buffer_store_b96(vdata, rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_store_b96' must be a constant integer}}
}
-void test_amdgcn_raw_ptr_buffer_store_b128(i128 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
+void test_amdgcn_raw_ptr_buffer_store_b128(v4u32 vdata, __amdgpu_buffer_rsrc_t rsrc, int offset, int soffset, int aux) {
__builtin_amdgcn_raw_buffer_store_b128(vdata, rsrc, /*offset=*/0, /*soffset=*/0, aux); //expected-error{{argument to '__builtin_amdgcn_raw_buffer_store_b128' must be a constant integer}}
}
diff --git a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp
index 94af968..23304ff 100644
--- a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp
+++ b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp
@@ -970,6 +970,23 @@ ort \
EXPECT_EQ(Directives[1].Kind, cxx_export_module_decl);
}
+TEST(MinimizeSourceToDependencyDirectivesTest, ObjCMethodArgs) {
+ SmallVector<char, 128> Out;
+
+ StringRef Source = R"(
+ @interface SomeObjcClass
+ - (void)func:(int)otherData
+ module:(int)module
+ import:(int)import;
+ @end
+ )";
+
+ ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
+ // `module :` and `import :` not followed by an identifier are not treated as
+ // directive lines because they can be method argument decls.
+ EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
+}
+
TEST(MinimizeSourceToDependencyDirectivesTest, TokensBeforeEOF) {
SmallString<128> Out;
diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake
index 80bbca1..5a97992 100644
--- a/compiler-rt/cmake/base-config-ix.cmake
+++ b/compiler-rt/cmake/base-config-ix.cmake
@@ -43,7 +43,7 @@ if (LLVM_TREE_AVAILABLE)
get_clang_resource_dir(COMPILER_RT_OUTPUT_DIR PREFIX ${LLVM_LIBRARY_OUTPUT_INTDIR}/..)
set(COMPILER_RT_EXEC_OUTPUT_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
get_clang_resource_dir(COMPILER_RT_INSTALL_PATH)
- option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests."
+ option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt tests."
${LLVM_INCLUDE_TESTS})
option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered"
${LLVM_ENABLE_WERROR})
@@ -70,7 +70,7 @@ else()
"Path where built compiler-rt executables should be stored.")
set(COMPILER_RT_INSTALL_PATH "" CACHE PATH
"Prefix for directories where built compiler-rt artifacts should be installed.")
- option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests." OFF)
+ option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt tests." OFF)
option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered" OFF)
# Use a host compiler to compile/link tests.
set(COMPILER_RT_TEST_COMPILER ${CMAKE_C_COMPILER} CACHE PATH "Compiler to use for testing")
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
index 16cdc4c..0b0bdb0 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
@@ -316,13 +316,13 @@ class SizeClassAllocator64 {
Printf(
"%s %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
"num_freed_chunks %7zd avail: %6zd rss: %6zdK releases: %6zd "
- "last released: %6lldK region: 0x%zx\n",
+ "last released: %6lldK region: %p\n",
region->exhausted ? "F" : " ", class_id, ClassIdToSize(class_id),
region->mapped_user >> 10, region->stats.n_allocated,
region->stats.n_freed, in_use, region->num_freed_chunks, avail_chunks,
rss >> 10, region->rtoi.num_releases,
region->rtoi.last_released_bytes >> 10,
- SpaceBeg() + kRegionSize * class_id);
+ (void *)(SpaceBeg() + kRegionSize * class_id));
}
void PrintStats() {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
index ce43269..506659a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
@@ -75,7 +75,8 @@ static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) {
if (!pc) continue;
if (!GetModuleAndOffsetForPc(pc, nullptr, 0, &pcs[i])) {
- Printf("ERROR: unknown pc 0x%zx (may happen if dlclose is used)\n", pc);
+ Printf("ERROR: unknown pc %p (may happen if dlclose is used)\n",
+ (void*)pc);
continue;
}
uptr module_base = pc - pcs[i];
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp
index b7fc944..f0e1e3d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp
@@ -105,8 +105,8 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
continue;
if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
continue;
- VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n",
- range.beg, range.end, mod.full_name());
+ VReport(1, "Adding instrumented range %p-%p from library '%s'\n",
+ (void *)range.beg, (void *)range.end, mod.full_name());
const uptr idx =
atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 794e3e7..47f9f0c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -2118,8 +2118,124 @@ bool SignalContext::IsTrueFaultingAddress() const {
return si->si_signo == SIGSEGV && si->si_code != 128;
}
+UNUSED
+static const char *RegNumToRegName(int reg) {
+ switch (reg) {
+# if defined(__x86_64__)
+ case REG_RAX:
+ return "rax";
+ case REG_RBX:
+ return "rbx";
+ case REG_RCX:
+ return "rcx";
+ case REG_RDX:
+ return "rdx";
+ case REG_RDI:
+ return "rdi";
+ case REG_RSI:
+ return "rsi";
+ case REG_RBP:
+ return "rbp";
+ case REG_RSP:
+ return "rsp";
+ case REG_R8:
+ return "r8";
+ case REG_R9:
+ return "r9";
+ case REG_R10:
+ return "r10";
+ case REG_R11:
+ return "r11";
+ case REG_R12:
+ return "r12";
+ case REG_R13:
+ return "r13";
+ case REG_R14:
+ return "r14";
+ case REG_R15:
+ return "r15";
+# elif defined(__i386__)
+ case REG_EAX:
+ return "eax";
+ case REG_EBX:
+ return "ebx";
+ case REG_ECX:
+ return "ecx";
+ case REG_EDX:
+ return "edx";
+ case REG_EDI:
+ return "edi";
+ case REG_ESI:
+ return "esi";
+ case REG_EBP:
+ return "ebp";
+ case REG_ESP:
+ return "esp";
+# endif
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
+UNUSED
+static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
+ const char *RegName = RegNumToRegName(RegNum);
+# if defined(__x86_64__)
+ Printf("%s%s = 0x%016llx ", internal_strlen(RegName) == 2 ? " " : "",
+ RegName, ctx->uc_mcontext.gregs[RegNum]);
+# elif defined(__i386__)
+ Printf("%s = 0x%08x ", RegName, ctx->uc_mcontext.gregs[RegNum]);
+# else
+ (void)RegName;
+# endif
+}
+
void SignalContext::DumpAllRegisters(void *context) {
- // FIXME: Implement this.
+# if SANITIZER_LINUX
+ ucontext_t *ucontext = (ucontext_t *)context;
+# if defined(__x86_64__)
+ Report("Register values:\n");
+ DumpSingleReg(ucontext, REG_RAX);
+ DumpSingleReg(ucontext, REG_RBX);
+ DumpSingleReg(ucontext, REG_RCX);
+ DumpSingleReg(ucontext, REG_RDX);
+ Printf("\n");
+ DumpSingleReg(ucontext, REG_RDI);
+ DumpSingleReg(ucontext, REG_RSI);
+ DumpSingleReg(ucontext, REG_RBP);
+ DumpSingleReg(ucontext, REG_RSP);
+ Printf("\n");
+ DumpSingleReg(ucontext, REG_R8);
+ DumpSingleReg(ucontext, REG_R9);
+ DumpSingleReg(ucontext, REG_R10);
+ DumpSingleReg(ucontext, REG_R11);
+ Printf("\n");
+ DumpSingleReg(ucontext, REG_R12);
+ DumpSingleReg(ucontext, REG_R13);
+ DumpSingleReg(ucontext, REG_R14);
+ DumpSingleReg(ucontext, REG_R15);
+ Printf("\n");
+# elif defined(__i386__)
+ // Duplication of this report print is caused by partial support
+ // of register values dumping. In case of unsupported yet architecture let's
+ // avoid printing 'Register values:' without actual values in the following
+ // output.
+ Report("Register values:\n");
+ DumpSingleReg(ucontext, REG_EAX);
+ DumpSingleReg(ucontext, REG_EBX);
+ DumpSingleReg(ucontext, REG_ECX);
+ DumpSingleReg(ucontext, REG_EDX);
+ Printf("\n");
+ DumpSingleReg(ucontext, REG_EDI);
+ DumpSingleReg(ucontext, REG_ESI);
+ DumpSingleReg(ucontext, REG_EBP);
+ DumpSingleReg(ucontext, REG_ESP);
+ Printf("\n");
+# endif
+ (void)ucontext;
+# endif
+ // FIXME: Implement this for other OSes and architectures.
}
static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
index cbdf3e9..8ebe37d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
@@ -1372,8 +1372,8 @@ void DumpProcessMap() {
for (uptr i = 0; i < modules.size(); ++i) {
char uuid_str[128];
FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
- Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
- modules[i].max_address(), modules[i].full_name(),
+ Printf("%p-%p %s (%s) %s\n", (void *)modules[i].base_address(),
+ (void *)modules[i].max_address(), modules[i].full_name(),
ModuleArchToString(modules[i].arch()), uuid_str);
}
Printf("End of module map.\n");
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp
index 969327a..7d7d575 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp
@@ -130,8 +130,8 @@ static void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem,
if (tolerate_enomem && reserrno == ENOMEM)
return nullptr;
char mem_type[40];
- internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
- fixed_addr);
+ internal_snprintf(mem_type, sizeof(mem_type), "memory at address %p",
+ (void *)fixed_addr);
ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
}
IncreaseTotalMmap(size);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index ece2d7d..9ffb36f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -327,9 +327,10 @@ static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags,
MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
int reserrno;
if (internal_iserror(p, &reserrno)) {
- Report("ERROR: %s failed to "
- "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
- SanitizerToolName, size, size, fixed_addr, reserrno);
+ Report(
+ "ERROR: %s failed to "
+ "allocate 0x%zx (%zd) bytes at address %p (errno: %d)\n",
+ SanitizerToolName, size, size, (void *)fixed_addr, reserrno);
return false;
}
IncreaseTotalMmap(size);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp
index b23796f..dddae44 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp
@@ -192,7 +192,7 @@ void FormattedStackTracePrinter::RenderFrame(InternalScopedString *buffer,
buffer->AppendF("%u", frame_no);
break;
case 'p':
- buffer->AppendF("0x%zx", address);
+ buffer->AppendF("%p", (void *)address);
break;
case 'm':
buffer->AppendF("%s", StripPathPrefix(info->module, strip_path_prefix));
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
index 25c4af7..526a71c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
@@ -257,8 +257,8 @@ static void TracerThreadDieCallback() {
static void TracerThreadSignalHandler(int signum, __sanitizer_siginfo *siginfo,
void *uctx) {
SignalContext ctx(siginfo, uctx);
- Printf("Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n", signum,
- ctx.addr, ctx.pc, ctx.sp);
+ Printf("Tracer caught signal %d: addr=%p pc=%p sp=%p\n", signum,
+ (void *)ctx.addr, (void *)ctx.pc, (void *)ctx.sp);
ThreadSuspender *inst = thread_suspender_instance;
if (inst) {
if (signum == SIGABRT)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
index 701db72..58a0cfd 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
@@ -158,8 +158,8 @@ static void TracerThreadDieCallback() {
static void TracerThreadSignalHandler(int signum, __sanitizer_siginfo *siginfo,
void *uctx) {
SignalContext ctx(siginfo, uctx);
- Printf("Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n", signum,
- ctx.addr, ctx.pc, ctx.sp);
+ Printf("Tracer caught signal %d: addr=%p pc=%p sp=%p\n", signum,
+ (void *)ctx.addr, (void *)ctx.pc, (void *)ctx.sp);
ThreadSuspender *inst = thread_suspender_instance;
if (inst) {
if (signum == SIGABRT)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
index 252979f..ee293bb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
@@ -121,25 +121,26 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
uptr tls_size = 0;
uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
VReport(2,
- "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: 0x%zx; sp: %p "
+ "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: %p; sp: %p "
"num_live_dtls %zd\n",
- (void *)arg, arg->dso_id, arg->offset, res, tls_beg, (void *)&tls_beg,
+ (void *)arg, arg->dso_id, arg->offset, res, (void *)tls_beg,
+ (void *)&tls_beg,
atomic_load(&number_of_live_dtls, memory_order_relaxed));
if (dtls.last_memalign_ptr == tls_beg) {
tls_size = dtls.last_memalign_size;
- VReport(2, "__tls_get_addr: glibc <=2.24 suspected; tls={0x%zx,0x%zx}\n",
- tls_beg, tls_size);
+ VReport(2, "__tls_get_addr: glibc <=2.24 suspected; tls={%p,0x%zx}\n",
+ (void *)tls_beg, tls_size);
} else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
// This is the static TLS block which was initialized / unpoisoned at thread
// creation.
- VReport(2, "__tls_get_addr: static tls: 0x%zx\n", tls_beg);
+ VReport(2, "__tls_get_addr: static tls: %p\n", (void *)tls_beg);
tls_size = 0;
} else if (const void *start =
__sanitizer_get_allocated_begin((void *)tls_beg)) {
tls_beg = (uptr)start;
tls_size = __sanitizer_get_allocated_size(start);
- VReport(2, "__tls_get_addr: glibc >=2.25 suspected; tls={0x%zx,0x%zx}\n",
- tls_beg, tls_size);
+ VReport(2, "__tls_get_addr: glibc >=2.25 suspected; tls={%p,0x%zx}\n",
+ (void *)tls_beg, tls_size);
} else {
VReport(2, "__tls_get_addr: Can't guess glibc version\n");
// This may happen inside the DTOR of main thread, so just ignore it.
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
index 0b19889..995f00e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -276,8 +276,8 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
MEM_COMMIT, PAGE_READWRITE);
if (p == 0) {
char mem_type[30];
- internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
- fixed_addr);
+ internal_snprintf(mem_type, sizeof(mem_type), "memory at address %p",
+ (void *)fixed_addr);
ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError());
}
return p;
@@ -308,8 +308,8 @@ void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) {
MEM_COMMIT, PAGE_READWRITE);
if (p == 0) {
char mem_type[30];
- internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
- fixed_addr);
+ internal_snprintf(mem_type, sizeof(mem_type), "memory at address %p",
+ (void *)fixed_addr);
return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
}
return p;
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp
index e810122..0283388 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp
@@ -100,11 +100,11 @@ TEST_F(StackDepotTest, Print) {
};
EXPECT_EXIT(
(StackDepotPrintAll(), exit(0)), ::testing::ExitedWithCode(0),
- fix_regex("Stack for id .*#0 0x1.*#1 0x2.*#2 0x3.*#3 0x4.*#4 0x7.*"));
- EXPECT_EXIT(
- (StackDepotPrintAll(), exit(0)), ::testing::ExitedWithCode(0),
fix_regex(
- "Stack for id .*#0 0x1.*#1 0x2.*#2 0x3.*#3 0x4.*#4 0x8.*#5 0x9.*"));
+ "Stack for id .*#0 0x0*1.*#1 0x0*2.*#2 0x0*3.*#3 0x0*4.*#4 0x0*7.*"));
+ EXPECT_EXIT((StackDepotPrintAll(), exit(0)), ::testing::ExitedWithCode(0),
+ fix_regex("Stack for id .*#0 0x0*1.*#1 0x0*2.*#2 0x0*3.*#3 "
+ "0x0*4.*#4 0x0*8.*#5 0x0*9.*"));
}
TEST_F(StackDepotTest, PrintNoLock) {
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp
index 9602ba3..76a434b 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp
@@ -11,9 +11,12 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_stacktrace_printer.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "interception/interception.h"
+using testing::MatchesRegex;
+
namespace __sanitizer {
class TestFormattedStackTracePrinter final : public FormattedStackTracePrinter {
@@ -96,10 +99,12 @@ TEST(FormattedStackTracePrinter, RenderFrame) {
"Function:%f FunctionOffset:%q Source:%s Line:%l "
"Column:%c",
frame_no, info.address, &info, false, "/path/to/");
- EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 "
- "Function:foo FunctionOffset:0x100 Source:my/source Line:10 "
- "Column:5",
- str.data());
+ EXPECT_THAT(
+ str.data(),
+ MatchesRegex(
+ "% Frame:42 PC:0x0*400000 Module:my/module ModuleOffset:0x200 "
+ "Function:foo FunctionOffset:0x100 Source:my/source Line:10 "
+ "Column:5"));
str.clear();
// Check that RenderFrame() strips interceptor prefixes.
@@ -109,10 +114,12 @@ TEST(FormattedStackTracePrinter, RenderFrame) {
"Function:%f FunctionOffset:%q Source:%s Line:%l "
"Column:%c",
frame_no, info.address, &info, false, "/path/to/");
- EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 "
- "Function:bar FunctionOffset:0x100 Source:my/source Line:10 "
- "Column:5",
- str.data());
+ EXPECT_THAT(
+ str.data(),
+ MatchesRegex(
+ "% Frame:42 PC:0x0*400000 Module:my/module ModuleOffset:0x200 "
+ "Function:bar FunctionOffset:0x100 Source:my/source Line:10 "
+ "Column:5"));
info.Clear();
str.clear();
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp
index 769a9b9..11ca1fd 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp
@@ -284,7 +284,7 @@ TEST(GetCurrentPc, Basic) {
StackTrace::GetCurrentPc(),
};
for (uptr i = 0; i < ARRAY_SIZE(pcs); i++)
- Printf("pc%zu: 0x%zx\n", i, pcs[i]);
+ Printf("pc%zu: %p\n", i, (void *)(pcs[i]));
for (uptr i = 1; i < ARRAY_SIZE(pcs); i++) {
EXPECT_GT(pcs[i], pcs[0]);
EXPECT_LT(pcs[i], pcs[0] + 1000);
diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt
index 83e4439..84a98f3 100644
--- a/compiler-rt/test/CMakeLists.txt
+++ b/compiler-rt/test/CMakeLists.txt
@@ -48,7 +48,7 @@ umbrella_lit_testsuite_begin(check-compiler-rt)
function(compiler_rt_test_runtime runtime)
string(TOUPPER ${runtime} runtime_uppercase)
- if(COMPILER_RT_HAS_${runtime_uppercase})
+ if(COMPILER_RT_HAS_${runtime_uppercase} AND COMPILER_RT_INCLUDE_TESTS)
if (${runtime} STREQUAL cfi AND NOT COMPILER_RT_HAS_UBSAN)
# CFI tests require diagnostic mode, which is implemented in UBSan.
elseif (${runtime} STREQUAL scudo_standalone)
diff --git a/compiler-rt/test/asan/CMakeLists.txt b/compiler-rt/test/asan/CMakeLists.txt
index 2d683e6..fb9e81b 100644
--- a/compiler-rt/test/asan/CMakeLists.txt
+++ b/compiler-rt/test/asan/CMakeLists.txt
@@ -130,39 +130,37 @@ if(APPLE)
endif()
# Add unit tests.
-if(COMPILER_RT_INCLUDE_TESTS)
- foreach(arch ${ASAN_TEST_ARCH})
- string(TOUPPER ${arch} ARCH_UPPER_CASE)
- set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
- set(CONFIG_NAME_DYNAMIC ${ARCH_UPPER_CASE}${OS_NAME}DynamicConfig)
+foreach(arch ${ASAN_TEST_ARCH})
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+ set(CONFIG_NAME_DYNAMIC ${ARCH_UPPER_CASE}${OS_NAME}DynamicConfig)
- if(NOT MINGW)
- # MinGW environments don't provide a statically linked CRT, so only the
- # dynamic asan test configuration can be expected to work.
- set(ASAN_TEST_DYNAMIC False)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME}/lit.site.cfg.py)
+ if(NOT MINGW)
+ # MinGW environments don't provide a statically linked CRT, so only the
+ # dynamic asan test configuration can be expected to work.
+ set(ASAN_TEST_DYNAMIC False)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME}/lit.site.cfg.py)
+ endif()
+ if(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME)
+ set(ASAN_TEST_DYNAMIC True)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME_DYNAMIC}/lit.site.cfg.py)
+ endif()
+ # FIXME: support unit test in the android test runner
+ if (NOT ANDROID)
+ if (NOT MINGW)
+ list(APPEND ASAN_TEST_DEPS AsanUnitTests)
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME})
endif()
if(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME)
- set(ASAN_TEST_DYNAMIC True)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME_DYNAMIC}/lit.site.cfg.py)
+ list(APPEND ASAN_DYNAMIC_TEST_DEPS AsanDynamicUnitTests)
+ list(APPEND ASAN_DYNAMIC_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME_DYNAMIC})
endif()
- # FIXME: support unit test in the android test runner
- if (NOT ANDROID)
- if (NOT MINGW)
- list(APPEND ASAN_TEST_DEPS AsanUnitTests)
- list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME})
- endif()
- if(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME)
- list(APPEND ASAN_DYNAMIC_TEST_DEPS AsanDynamicUnitTests)
- list(APPEND ASAN_DYNAMIC_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME_DYNAMIC})
- endif()
- endif()
- endforeach()
-endif()
+ endif()
+endforeach()
if (SHADOW_MAPPING_UNRELIABLE)
set(exclude_from_check_all.g "EXCLUDE_FROM_CHECK_ALL")
diff --git a/compiler-rt/test/ctx_profile/CMakeLists.txt b/compiler-rt/test/ctx_profile/CMakeLists.txt
index 371f1a2..fc3b3f3 100644
--- a/compiler-rt/test/ctx_profile/CMakeLists.txt
+++ b/compiler-rt/test/ctx_profile/CMakeLists.txt
@@ -25,17 +25,15 @@ foreach(arch ${CTX_PROFILE_SUPPORTED_ARCH})
endforeach()
# Add unit tests.
-if(COMPILER_RT_INCLUDE_TESTS)
- foreach(arch ${CTX_PROFILE_SUPPORTED_ARCH})
- string(TOUPPER ${arch} ARCH_UPPER_CASE)
- set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME}/lit.site.cfg.py)
- list(APPEND CTX_PROFILE_TEST_DEPS CtxProfileUnitTests)
- list(APPEND CTX_PROFILE_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME})
- endforeach()
-endif()
+foreach(arch ${CTX_PROFILE_SUPPORTED_ARCH})
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME}/lit.site.cfg.py)
+ list(APPEND CTX_PROFILE_TEST_DEPS CtxProfileUnitTests)
+ list(APPEND CTX_PROFILE_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME})
+endforeach()
add_lit_testsuite(check-ctx_profile "Running the Contextual Profiler tests"
${CTX_PROFILE_TESTSUITES}
diff --git a/compiler-rt/test/fuzzer/CMakeLists.txt b/compiler-rt/test/fuzzer/CMakeLists.txt
index 8d29a4b..b19f52e 100644
--- a/compiler-rt/test/fuzzer/CMakeLists.txt
+++ b/compiler-rt/test/fuzzer/CMakeLists.txt
@@ -22,20 +22,16 @@ if (APPLE)
darwin_filter_host_archs(FUZZER_SUPPORTED_ARCH FUZZER_TEST_ARCH)
endif()
-if(COMPILER_RT_INCLUDE_TESTS)
- list(APPEND LIBFUZZER_TEST_DEPS FuzzerUnitTests)
- list(APPEND LIBFUZZER_TEST_DEPS FuzzedDataProviderUnitTests)
-endif()
+list(APPEND LIBFUZZER_TEST_DEPS FuzzerUnitTests)
+list(APPEND LIBFUZZER_TEST_DEPS FuzzedDataProviderUnitTests)
set(LIBFUZZER_TESTSUITES)
-if(COMPILER_RT_INCLUDE_TESTS)
- # libFuzzer unit tests.
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg.py)
- list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit)
-endif()
+# libFuzzer unit tests.
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg.py)
+list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit)
macro(test_fuzzer stdlib)
cmake_parse_arguments(TEST "" "" "DEPS" ${ARGN})
diff --git a/compiler-rt/test/gwp_asan/CMakeLists.txt b/compiler-rt/test/gwp_asan/CMakeLists.txt
index f9580e2..6ffa36e 100644
--- a/compiler-rt/test/gwp_asan/CMakeLists.txt
+++ b/compiler-rt/test/gwp_asan/CMakeLists.txt
@@ -14,7 +14,7 @@ set(GWP_ASAN_TEST_DEPS
# exported libc++ from the Android NDK is x86-64, even though it's part of the
# ARM[64] toolchain... See similar measures for ASan and sanitizer-common that
# disable unit tests for Android.
-if (COMPILER_RT_INCLUDE_TESTS AND NOT ANDROID)
+if (NOT ANDROID)
list(APPEND GWP_ASAN_TEST_DEPS GwpAsanUnitTests)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.py.in
@@ -22,7 +22,7 @@ if (COMPILER_RT_INCLUDE_TESTS AND NOT ANDROID)
list(APPEND GWP_ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit)
endif()
-if (COMPILER_RT_INCLUDE_TESTS AND COMPILER_RT_HAS_SCUDO_STANDALONE)
+if (COMPILER_RT_HAS_SCUDO_STANDALONE)
foreach(arch ${GWP_ASAN_SUPPORTED_ARCH})
set(GWP_ASAN_TEST_TARGET_ARCH ${arch})
string(TOLOWER "-${arch}" GWP_ASAN_TEST_CONFIG_SUFFIX)
diff --git a/compiler-rt/test/interception/CMakeLists.txt b/compiler-rt/test/interception/CMakeLists.txt
index df69453..8ed1a00 100644
--- a/compiler-rt/test/interception/CMakeLists.txt
+++ b/compiler-rt/test/interception/CMakeLists.txt
@@ -3,7 +3,7 @@ set(INTERCEPTION_TESTSUITES)
# Unit tests. There are currently no unit tests capable to running on Apple or
# Android targets.
-if(COMPILER_RT_INCLUDE_TESTS AND NOT ANDROID AND NOT APPLE)
+if(NOT ANDROID AND NOT APPLE)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
diff --git a/compiler-rt/test/memprof/CMakeLists.txt b/compiler-rt/test/memprof/CMakeLists.txt
index 0012452..4c50ae6 100644
--- a/compiler-rt/test/memprof/CMakeLists.txt
+++ b/compiler-rt/test/memprof/CMakeLists.txt
@@ -44,17 +44,15 @@ foreach(arch ${MEMPROF_TEST_ARCH})
endforeach()
# Add unit tests.
-if(COMPILER_RT_INCLUDE_TESTS)
- foreach(arch ${MEMPROF_TEST_ARCH})
- string(TOUPPER ${arch} ARCH_UPPER_CASE)
- set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME}/lit.site.cfg.py)
- list(APPEND MEMPROF_TEST_DEPS MemProfUnitTests)
- list(APPEND MEMPROF_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME})
- endforeach()
-endif()
+foreach(arch ${MEMPROF_TEST_ARCH})
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME}/lit.site.cfg.py)
+ list(APPEND MEMPROF_TEST_DEPS MemProfUnitTests)
+ list(APPEND MEMPROF_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME})
+endforeach()
add_lit_testsuite(check-memprof "Running the MemProfiler tests"
${MEMPROF_TESTSUITES}
diff --git a/compiler-rt/test/msan/CMakeLists.txt b/compiler-rt/test/msan/CMakeLists.txt
index ff19c11..df571976 100644
--- a/compiler-rt/test/msan/CMakeLists.txt
+++ b/compiler-rt/test/msan/CMakeLists.txt
@@ -41,9 +41,7 @@ foreach(arch ${MSAN_TEST_ARCH})
endif()
endforeach()
-if(COMPILER_RT_INCLUDE_TESTS AND
- COMPILER_RT_LIBCXX_PATH AND
- COMPILER_RT_LIBCXXABI_PATH)
+if(COMPILER_RT_LIBCXX_PATH AND COMPILER_RT_LIBCXXABI_PATH)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
diff --git a/compiler-rt/test/nsan/CMakeLists.txt b/compiler-rt/test/nsan/CMakeLists.txt
index fb73587..d702e12 100644
--- a/compiler-rt/test/nsan/CMakeLists.txt
+++ b/compiler-rt/test/nsan/CMakeLists.txt
@@ -3,9 +3,7 @@ set(NSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(NSAN_TESTSUITES)
set(NSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} nsan)
-if(COMPILER_RT_INCLUDE_TESTS AND
- COMPILER_RT_LIBCXX_PATH AND
- COMPILER_RT_LIBCXXABI_PATH)
+if(COMPILER_RT_LIBCXX_PATH AND COMPILER_RT_LIBCXXABI_PATH)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
diff --git a/compiler-rt/test/rtsan/CMakeLists.txt b/compiler-rt/test/rtsan/CMakeLists.txt
index 2a59a57..e1f9eb3 100644
--- a/compiler-rt/test/rtsan/CMakeLists.txt
+++ b/compiler-rt/test/rtsan/CMakeLists.txt
@@ -34,20 +34,18 @@ foreach(arch ${RTSAN_TEST_ARCH})
list(APPEND RTSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
endforeach()
-if(COMPILER_RT_INCLUDE_TESTS)
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
+if(COMPILER_RT_RTSAN_HAS_STATIC_RUNTIME)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
- if(COMPILER_RT_RTSAN_HAS_STATIC_RUNTIME)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic/lit.site.cfg.py)
- endif()
- list(APPEND RTSAN_TEST_DEPS RtsanUnitTests)
- list(APPEND RTSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
- if(COMPILER_RT_RTSAN_HAS_STATIC_RUNTIME)
- list(APPEND RTSAN_DYNAMIC_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic)
- endif()
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic/lit.site.cfg.py)
+endif()
+list(APPEND RTSAN_TEST_DEPS RtsanUnitTests)
+list(APPEND RTSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
+if(COMPILER_RT_RTSAN_HAS_STATIC_RUNTIME)
+ list(APPEND RTSAN_DYNAMIC_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic)
endif()
add_lit_testsuite(check-rtsan "Running the Rtsan tests"
diff --git a/compiler-rt/test/sanitizer_common/CMakeLists.txt b/compiler-rt/test/sanitizer_common/CMakeLists.txt
index edecc04..fa06b82 100644
--- a/compiler-rt/test/sanitizer_common/CMakeLists.txt
+++ b/compiler-rt/test/sanitizer_common/CMakeLists.txt
@@ -99,15 +99,13 @@ foreach(tool ${SUPPORTED_TOOLS})
endforeach()
# Unit tests.
-if(COMPILER_RT_INCLUDE_TESTS)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
- # FIXME: support unit test in the android test runner
- if (NOT ANDROID)
- list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
- list(APPEND SANITIZER_COMMON_TEST_DEPS SanitizerUnitTests)
- endif()
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
+# FIXME: support unit test in the android test runner
+if (NOT ANDROID)
+ list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
+ list(APPEND SANITIZER_COMMON_TEST_DEPS SanitizerUnitTests)
endif()
if(SANITIZER_COMMON_TESTSUITES)
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_i386.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_i386.cpp
new file mode 100644
index 0000000..74aea4d
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_i386.cpp
@@ -0,0 +1,17 @@
+// Check that sanitizer prints registers dump_registers on dump_registers=1
+// RUN: %clangxx %s -o %t
+// RUN: %env_tool_opts=dump_registers=0 not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-NODUMP --strict-whitespace
+// RUN: not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-DUMP --strict-whitespace
+//
+// REQUIRES: i386-target-arch
+
+#include <signal.h>
+
+int main() {
+ raise(SIGSEGV);
+ // CHECK-DUMP: Register values
+ // CHECK-DUMP-NEXT: eax = {{0x[0-9a-f]+}} ebx = {{0x[0-9a-f]+}} ecx = {{0x[0-9a-f]+}} edx = {{0x[0-9a-f]+}}
+ // CHECK-DUMP-NEXT: edi = {{0x[0-9a-f]+}} esi = {{0x[0-9a-f]+}} ebp = {{0x[0-9a-f]+}} esp = {{0x[0-9a-f]+}}
+ // CHECK-NODUMP-NOT: Register values
+ return 0;
+}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_x86_64.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_x86_64.cpp
new file mode 100644
index 0000000..3d11ef0
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_x86_64.cpp
@@ -0,0 +1,19 @@
+// Check that sanitizer prints registers dump_registers on dump_registers=1
+// RUN: %clangxx %s -o %t
+// RUN: %env_tool_opts=dump_registers=0 not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-NODUMP --strict-whitespace
+// RUN: not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-DUMP --strict-whitespace
+//
+// REQUIRES: x86_64-target-arch
+
+#include <signal.h>
+
+int main() {
+ raise(SIGSEGV);
+ // CHECK-DUMP: Register values
+ // CHECK-DUMP-NEXT: rax = {{0x[0-9a-f]+}} rbx = {{0x[0-9a-f]+}} rcx = {{0x[0-9a-f]+}} rdx = {{0x[0-9a-f]+}}
+ // CHECK-DUMP-NEXT: rdi = {{0x[0-9a-f]+}} rsi = {{0x[0-9a-f]+}} rbp = {{0x[0-9a-f]+}} rsp = {{0x[0-9a-f]+}}
+ // CHECK-DUMP-NEXT: r8 = {{0x[0-9a-f]+}} r9 = {{0x[0-9a-f]+}} r10 = {{0x[0-9a-f]+}} r11 = {{0x[0-9a-f]+}}
+ // CHECK-DUMP-NEXT: r12 = {{0x[0-9a-f]+}} r13 = {{0x[0-9a-f]+}} r14 = {{0x[0-9a-f]+}} r15 = {{0x[0-9a-f]+}}
+ // CHECK-NODUMP-NOT: Register values
+ return 0;
+}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp
index 286eafc..21ffe13 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp
@@ -14,15 +14,12 @@ int main(int argc, char **argv) {
sprintf(buff, "%s.report_path/report", argv[0]);
__sanitizer_set_report_path(buff);
assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0);
- printf("Path %s\n", __sanitizer_get_report_path());
- fflush(stdout);
// Try setting again with an invalid/inaccessible directory.
- sprintf(buff, "%s/report", argv[0]);
- __sanitizer_set_report_path(buff);
- printf("Path %s\n", __sanitizer_get_report_path());
+ char buff_bad[1000];
+ sprintf(buff_bad, "%s/report", argv[0]);
+ __sanitizer_set_report_path(buff_bad);
+ assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0);
}
-// CHECK: Path {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path/report.
// CHECK: ERROR: Can't create directory: {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp
-// CHECK-NOT: Path {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp
diff --git a/compiler-rt/test/scudo/standalone/CMakeLists.txt b/compiler-rt/test/scudo/standalone/CMakeLists.txt
index 0034cea..3e6c8ab 100644
--- a/compiler-rt/test/scudo/standalone/CMakeLists.txt
+++ b/compiler-rt/test/scudo/standalone/CMakeLists.txt
@@ -1,21 +1,19 @@
-if(COMPILER_RT_INCLUDE_TESTS)
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg.py)
+list(APPEND SCUDO_STANDALONE_TEST_DEPS ScudoUnitTests)
+list(APPEND SCUDO_STANDALONE_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit)
+if (COMPILER_RT_HAS_GWP_ASAN)
configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg.py)
- list(APPEND SCUDO_STANDALONE_TEST_DEPS ScudoUnitTests)
- list(APPEND SCUDO_STANDALONE_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit)
- if (COMPILER_RT_HAS_GWP_ASAN)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/unit/gwp_asan/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/unit/gwp_asan/lit.site.cfg.py)
- list(APPEND SCUDO_STANDALONE_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit/gwp_asan)
- endif()
+ ${CMAKE_CURRENT_SOURCE_DIR}/unit/gwp_asan/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/unit/gwp_asan/lit.site.cfg.py)
+ list(APPEND SCUDO_STANDALONE_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit/gwp_asan)
+endif()
- add_lit_testsuite(check-scudo_standalone
- "Running Scudo Standalone tests"
- ${SCUDO_STANDALONE_TESTSUITES}
- DEPENDS ${SCUDO_STANDALONE_TEST_DEPS})
+add_lit_testsuite(check-scudo_standalone
+ "Running Scudo Standalone tests"
+ ${SCUDO_STANDALONE_TESTSUITES}
+ DEPENDS ${SCUDO_STANDALONE_TEST_DEPS})
- set_target_properties(check-scudo_standalone
- PROPERTIES FOLDER "Compiler-RT Tests")
-endif()
+set_target_properties(check-scudo_standalone
+ PROPERTIES FOLDER "Compiler-RT Tests")
diff --git a/compiler-rt/test/tsan/CMakeLists.txt b/compiler-rt/test/tsan/CMakeLists.txt
index 31cda53..163355d 100644
--- a/compiler-rt/test/tsan/CMakeLists.txt
+++ b/compiler-rt/test/tsan/CMakeLists.txt
@@ -111,20 +111,18 @@ if(APPLE)
endforeach()
endif()
-if(COMPILER_RT_INCLUDE_TESTS)
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
+if(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py)
- if(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME)
- configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic/lit.site.cfg.py)
- endif()
- list(APPEND TSAN_TEST_DEPS TsanUnitTests)
- list(APPEND TSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
- if(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME)
- list(APPEND TSAN_DYNAMIC_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic)
- endif()
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic/lit.site.cfg.py)
+endif()
+list(APPEND TSAN_TEST_DEPS TsanUnitTests)
+list(APPEND TSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
+if(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME)
+ list(APPEND TSAN_DYNAMIC_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic)
endif()
add_lit_testsuite(check-tsan "Running ThreadSanitizer tests"
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 82f9a02..093596c 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -134,6 +134,13 @@ end
implicitly simply appearing in an asynchronous data transfer statement,
without the attribute being visible in the procedure's explicit
interface.
+* When the name of an extended derived type's base type is the
+ result of `USE` association with renaming, the name of the extended
+ derived type's parent component is the new name by which the base
+ is known in the scope of the extended derived type, not the original.
+ This interpretation has usability advantages and is what six other
+ Fortran compilers do, but is not conforming now that J3 approved an
+ "interp" in June 2024 to the contrary.
## Extensions, deletions, and legacy features supported by default
diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp
index 746d04a..0bdc4c4 100644
--- a/flang/lib/Parser/Fortran-parsers.cpp
+++ b/flang/lib/Parser/Fortran-parsers.cpp
@@ -1304,10 +1304,16 @@ TYPE_PARSER(extension<LanguageFeature::CUDA>(construct<CUDAAttributesStmt>(
defaulted(
maybe("::"_tok) >> nonemptyList("expected names"_err_en_US, name)))))
-// Subtle: the name includes the surrounding slashes, which avoids
+// Subtle: A structure's name includes the surrounding slashes, which avoids
// clashes with other uses of the name in the same scope.
-TYPE_PARSER(construct<StructureStmt>(
- "STRUCTURE" >> maybe(sourced("/" >> name / "/")), optionalList(entityDecl)))
+constexpr auto structureName{maybe(sourced("/" >> name / "/"))};
+
+// Note that Parser<StructureStmt>{} has a mandatory list of entity-decls
+// and is used only by NestedStructureStmt{}.Parse() in user-state.cpp.
+TYPE_PARSER(construct<StructureStmt>("STRUCTURE" >> structureName,
+ localRecovery(
+ "entity declarations are required on a nested structure"_err_en_US,
+ nonemptyList(entityDecl), ok)))
constexpr auto nestedStructureDef{
CONTEXT_PARSER("nested STRUCTURE definition"_en_US,
@@ -1323,7 +1329,9 @@ TYPE_PARSER(construct<StructureField>(statement(StructureComponents{})) ||
TYPE_CONTEXT_PARSER("STRUCTURE definition"_en_US,
extension<LanguageFeature::DECStructures>(
"nonstandard usage: STRUCTURE"_port_en_US,
- construct<StructureDef>(statement(Parser<StructureStmt>{}),
+ construct<StructureDef>(
+ statement(construct<StructureStmt>(
+ "STRUCTURE" >> structureName, optionalList(entityDecl))),
many(Parser<StructureField>{}),
statement(construct<StructureDef::EndStructureStmt>(
"END STRUCTURE"_tok)))))
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index ca6a823..aa45548 100644
--- a/flang/lib/Parser/prescan.cpp
+++ b/flang/lib/Parser/prescan.cpp
@@ -189,11 +189,19 @@ void Prescanner::Statement() {
// a comment marker or directive sentinel. If so, disable line
// continuation, so that NextToken() won't consume anything from
// following lines.
- if (IsLegalIdentifierStart(*at_) && NextToken(tokens) &&
- tokens.SizeInTokens() > 0) {
- if (CharBlock id{tokens.TokenAt(0)}; preprocessor_.IsNameDefined(id) &&
+ if (IsLegalIdentifierStart(*at_)) {
+ // TODO: Only bother with these cases when any keyword macro has
+ // been defined with replacement text that could begin a comment
+ // or directive sentinel.
+ const char *p{at_};
+ while (IsLegalInIdentifier(*++p)) {
+ }
+ CharBlock id{at_, static_cast<std::size_t>(p - at_)};
+ if (preprocessor_.IsNameDefined(id) &&
!preprocessor_.IsFunctionLikeDefinition(id)) {
- if (auto replaced{preprocessor_.MacroReplacement(tokens, *this)}) {
+ TokenSequence toks;
+ toks.Put(id, GetProvenance(at_));
+ if (auto replaced{preprocessor_.MacroReplacement(toks, *this)}) {
auto newLineClass{ClassifyLine(*replaced, GetCurrentProvenance())};
disableSourceContinuation_ =
newLineClass.kind != LineClassification::Kind::Source;
diff --git a/flang/lib/Semantics/definable.cpp b/flang/lib/Semantics/definable.cpp
index 96af46a..d594b1e 100644
--- a/flang/lib/Semantics/definable.cpp
+++ b/flang/lib/Semantics/definable.cpp
@@ -178,7 +178,10 @@ static std::optional<parser::Message> WhyNotDefinableBase(parser::CharBlock at,
static std::optional<parser::Message> WhyNotDefinableLast(parser::CharBlock at,
const Scope &scope, DefinabilityFlags flags, const Symbol &original) {
const Symbol &ultimate{original.GetUltimate()};
- if (const auto *association{ultimate.detailsIf<AssocEntityDetails>()}) {
+ if (const auto *association{ultimate.detailsIf<AssocEntityDetails>()};
+ association &&
+ (association->rank().has_value() ||
+ !flags.test(DefinabilityFlag::PointerDefinition))) {
if (auto dataRef{
evaluate::ExtractDataRef(*association->expr(), true, true)}) {
return WhyNotDefinableLast(at, scope, flags, dataRef->GetLastSymbol());
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 2d91962..4413d77 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -4533,6 +4533,8 @@ std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
!OkLogicalIntegerAssignment(lhsType->category(), rhsType->category())) {
SayNoMatch("ASSIGNMENT(=)", true);
}
+ } else if (!fatalErrors_) {
+ CheckAssignmentConformance();
}
return std::nullopt;
}
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index a11f444..5c5bca8 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -268,6 +268,7 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
recordOffsetInFrame_ = 0;
}
BeginRecord();
+ leftTabLimit.reset();
}
bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
diff --git a/flang/test/Preprocessing/directive-contin-with-pp.F90 b/flang/test/Preprocessing/directive-contin-with-pp.F90
index 64f1dc4..544c6619f 100644
--- a/flang/test/Preprocessing/directive-contin-with-pp.F90
+++ b/flang/test/Preprocessing/directive-contin-with-pp.F90
@@ -11,7 +11,7 @@
module m
contains
- subroutine s(x1, x2, x3, x4, x5, x6, x7)
+ subroutine s1(x1, x2, x3, x4, x5, x6, x7)
!dir$ ignore_tkr x1
@@ -51,11 +51,18 @@ OMP_CONT reduction(+:x)
do j3 = 1, n
end do
end
-end
+
+COMMENT &
+ subroutine s2
+ end subroutine
+COMMENT&
+ subroutine s3
+ end subroutine
+end module
!CHECK: MODULE m
!CHECK: CONTAINS
-!CHECK: SUBROUTINE s (x1, x2, x3, x4, x5, x6, x7)
+!CHECK: SUBROUTINE s1 (x1, x2, x3, x4, x5, x6, x7)
!CHECK: !DIR$ IGNORE_TKR x1
!CHECK: !DIR$ IGNORE_TKR x2
!CHECK: !DIR$ IGNORE_TKR x3
@@ -73,4 +80,8 @@ end
!CHECK: DO j3=1_4,n
!CHECK: END DO
!CHECK: END SUBROUTINE
+!CHECK: SUBROUTINE s2
+!CHECK: END SUBROUTINE
+!CHECK: SUBROUTINE s3
+!CHECK: END SUBROUTINE
!CHECK: END MODULE
diff --git a/flang/test/Semantics/array-constr-values.f90 b/flang/test/Semantics/array-constr-values.f90
index b93f774..6742cd3 100644
--- a/flang/test/Semantics/array-constr-values.f90
+++ b/flang/test/Semantics/array-constr-values.f90
@@ -35,8 +35,10 @@ subroutine arrayconstructorvalues()
intarray = [integer:: EMPLOYEE (19, "Jack"), 2, 3, 4, 5]
! C7112
+ !ERROR: Dimension 1 of left-hand side has extent 3, but right-hand side has extent 2
!ERROR: Value in array constructor of type 'INTEGER(4)' could not be converted to the type of the array 'employee'
emparray = (/ EMPLOYEE:: EMPLOYEE(19, "Ganesh"), EMPLOYEE(22, "Omkar"), 19 /)
+ !ERROR: Dimension 1 of left-hand side has extent 3, but right-hand side has extent 2
!ERROR: Value in array constructor of type 'employeer' could not be converted to the type of the array 'employee'
emparray = (/ EMPLOYEE:: EMPLOYEE(19, "Ganesh"), EMPLOYEE(22, "Ram"),EMPLOYEER("ShriniwasPvtLtd") /)
diff --git a/flang/test/Semantics/assign10.f90 b/flang/test/Semantics/assign10.f90
index 6b98097b..f0ea4b2 100644
--- a/flang/test/Semantics/assign10.f90
+++ b/flang/test/Semantics/assign10.f90
@@ -1,7 +1,11 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
! Shape conformance checks on assignments
program test
+ type t
+ integer n
+ end type
real :: a0, a1a(2), a1b(3), a2a(2,3), a2b(3,2)
+ type(t) c(10)
a0 = 0. ! ok
!ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar REAL(4) and rank 1 array of REAL(4)
a0 = [0.]
@@ -20,4 +24,6 @@ program test
a2a(1,:) = a1a
!ERROR: Dimension 1 of left-hand side has extent 2, but right-hand side has extent 3
a2a = a2b
+ !ERROR: Dimension 1 of left-hand side has extent 10, but right-hand side has extent 0
+ c(1:10) = c(10:1)
end
diff --git a/flang/test/Semantics/associate03.f90 b/flang/test/Semantics/associate03.f90
new file mode 100644
index 0000000..f57dc17
--- /dev/null
+++ b/flang/test/Semantics/associate03.f90
@@ -0,0 +1,79 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
+! A construct entity does not have the POINTER or ALLOCATABLE attribute,
+! except in SELECT RANK.
+
+subroutine test(up,ua,rp,ra)
+ class(*), pointer :: up
+ class(*), allocatable :: ua
+ real, pointer :: rp(..)
+ real, allocatable :: ra(..)
+ real, target :: x
+ real, pointer :: p
+ real, allocatable :: a
+ associate (s => p)
+ !ERROR: The left-hand side of a pointer assignment is not definable
+ !BECAUSE: 's' is not a pointer
+ s => x
+ !ERROR: Entity in ALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ allocate(s)
+ !ERROR: Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ deallocate(s)
+ !ERROR: 's' may not appear in NULLIFY
+ !BECAUSE: 's' is not a pointer
+ nullify(s)
+ end associate
+ select type(s => up)
+ type is (real)
+ !ERROR: The left-hand side of a pointer assignment is not definable
+ !BECAUSE: 's' is not a pointer
+ s => x
+ !ERROR: Entity in ALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ allocate(s)
+ !ERROR: Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ deallocate(s)
+ !ERROR: 's' may not appear in NULLIFY
+ !BECAUSE: 's' is not a pointer
+ nullify(s)
+ end select
+ select rank(s => rp)
+ rank(0)
+ s => x ! ok
+ allocate(s) ! ok
+ deallocate(s) ! ok
+ nullify(s) ! ok
+ !ERROR: RANK (*) cannot be used when selector is POINTER or ALLOCATABLE
+ rank(*)
+ rank default
+ !ERROR: The left-hand side of a pointer assignment must not be an assumed-rank dummy argument
+ !ERROR: pointer 's' associated with object 'x' with incompatible type or shape
+ s => x
+ !ERROR: An assumed-rank dummy argument may not appear in an ALLOCATE statement
+ allocate(s)
+ deallocate(s) ! ok
+ nullify(s) ! ok
+ end select
+ associate (s => a)
+ !ERROR: Entity in ALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ allocate(s)
+ !ERROR: Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ deallocate(s)
+ end associate
+ select type(s => ua)
+ type is (real)
+ !ERROR: Entity in ALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ allocate(s)
+ !ERROR: Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+ deallocate(s)
+ end select
+ select rank(s => ra)
+ rank(0)
+ allocate(s) ! ok
+ deallocate(s) ! ok
+ !ERROR: RANK (*) cannot be used when selector is POINTER or ALLOCATABLE
+ rank(*)
+ rank default
+ !ERROR: An assumed-rank dummy argument may not appear in an ALLOCATE statement
+ allocate(s)
+ deallocate(s) ! ok
+ end select
+end
diff --git a/flang/test/Semantics/parent-comp-name.f90 b/flang/test/Semantics/parent-comp-name.f90
new file mode 100644
index 0000000..d787843
--- /dev/null
+++ b/flang/test/Semantics/parent-comp-name.f90
@@ -0,0 +1,70 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Every other Fortran compiler (but one) interprets the names of parent
+! components like this when the names of their types are the product of
+! USE association with renaming.
+
+module m1
+ type originalName
+ integer m
+ end type
+end
+
+module m2
+ use m1, newName => originalName
+ type, extends(newName) :: extended
+ integer n
+ end type
+ type, extends(newName) :: extended2
+ integer originalName ! ok
+ end type
+ contains
+ subroutine s1
+ type(extended) x
+ type(extended2) x2
+ print *, x%newName%m ! ok
+ !ERROR: Component 'originalname' not found in derived type 'extended'
+ print *, x%originalName
+ print *, extended(newName=newName(m=1),n=2) ! ok
+ !ERROR: Structure constructor lacks a value for component 'm'
+ !ERROR: Keyword 'originalname=' does not name a component of derived type 'extended'
+ !ERROR: Keyword 'm=' may not appear in a reference to a procedure with an implicit interface
+ print *, extended(originalName=originalName(m=1),n=2)
+ !ERROR: Value in structure constructor of type 'REAL(4)' is incompatible with component 'newname' of type 'newname'
+ !ERROR: Keyword 'm=' may not appear in a reference to a procedure with an implicit interface
+ print *, extended(newName=originalName(m=1),n=2)
+ !ERROR: Structure constructor lacks a value for component 'm'
+ !ERROR: Keyword 'originalname=' does not name a component of derived type 'extended'
+ print *, extended(originalName=newName(m=1),n=2)
+ print *, x2%newName%m ! ok
+ print *, x2%originalName ! ok
+ print *, extended2(newName=newName(m=1),originalName=2) ! ok
+ end
+end
+
+module m3
+ use m2
+ contains
+ ! Same as above, but not in the same module as the derived
+ ! types' definitions.
+ subroutine s2
+ type(extended) x
+ type(extended2) x2
+ print *, x%newName%m ! ok
+ !ERROR: Component 'originalname' not found in derived type 'extended'
+ print *, x%originalName
+ print *, extended(newName=newName(m=1),n=2) ! ok
+ !ERROR: Structure constructor lacks a value for component 'm'
+ !ERROR: Keyword 'originalname=' does not name a component of derived type 'extended'
+ !ERROR: Keyword 'm=' may not appear in a reference to a procedure with an implicit interface
+ print *, extended(originalName=originalName(m=1),n=2)
+ !ERROR: Value in structure constructor of type 'REAL(4)' is incompatible with component 'newname' of type 'newname'
+ !ERROR: Keyword 'm=' may not appear in a reference to a procedure with an implicit interface
+ print *, extended(newName=originalName(m=1),n=2)
+ !ERROR: Structure constructor lacks a value for component 'm'
+ !ERROR: Keyword 'originalname=' does not name a component of derived type 'extended'
+ print *, extended(originalName=newName(m=1),n=2)
+ print *, x2%newName%m ! ok
+ print *, x2%originalName ! ok
+ print *, extended2(newName=newName(m=1),originalName=2) ! ok
+ end
+end
diff --git a/flang/test/Semantics/struct03.f90 b/flang/test/Semantics/struct03.f90
new file mode 100644
index 0000000..a334cca
--- /dev/null
+++ b/flang/test/Semantics/struct03.f90
@@ -0,0 +1,7 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+ structure /s/
+ !ERROR: entity declarations are required on a nested structure
+ structure /nested/
+ end structure
+ end structure
+end
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 6ba5447..6e07607 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -73,6 +73,8 @@ if(LIBC_BUILD_GPU_LOADER OR (LLVM_LIBC_GPU_BUILD AND NOT LLVM_RUNTIMES_BUILD))
add_subdirectory(utils/gpu)
endif()
+option(LIBC_USE_NEW_HEADER_GEN "Generate header files using new headergen instead of the old one" OFF)
+
set(NEED_LIBC_HDRGEN FALSE)
if(NOT LLVM_RUNTIMES_BUILD)
if("libc" IN_LIST LLVM_ENABLE_RUNTIMES)
diff --git a/libc/cmake/modules/LLVMLibCHeaderRules.cmake b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
index 7fc6860..3049f4d 100644
--- a/libc/cmake/modules/LLVMLibCHeaderRules.cmake
+++ b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
@@ -66,7 +66,107 @@ function(add_header target_name)
)
endfunction(add_header)
-# A rule for generated header file targets.
+function(add_gen_header2 target_name)
+ cmake_parse_arguments(
+ "ADD_GEN_HDR2"
+ "PUBLIC" # No optional arguments
+ "YAML_FILE;DEF_FILE;GEN_HDR" # Single value arguments
+ "DEPENDS" # Multi value arguments
+ ${ARGN}
+ )
+ get_fq_target_name(${target_name} fq_target_name)
+ if(NOT LLVM_LIBC_FULL_BUILD)
+ add_library(${fq_target_name} INTERFACE)
+ return()
+ endif()
+ if(NOT ADD_GEN_HDR2_DEF_FILE)
+ message(FATAL_ERROR "`add_gen_hdr2` rule requires DEF_FILE to be specified.")
+ endif()
+ if(NOT ADD_GEN_HDR2_GEN_HDR)
+ message(FATAL_ERROR "`add_gen_hdr2` rule requires GEN_HDR to be specified.")
+ endif()
+ if(NOT ADD_GEN_HDR2_YAML_FILE)
+ message(FATAL_ERROR "`add_gen_hdr2` rule requires YAML_FILE to be specified.")
+ endif()
+
+ set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR2_GEN_HDR})
+ file(RELATIVE_PATH relative_path ${LIBC_INCLUDE_SOURCE_DIR} ${absolute_path})
+ set(out_file ${LIBC_INCLUDE_DIR}/${relative_path})
+ set(yaml_file ${CMAKE_SOURCE_DIR}/${ADD_GEN_HDR2_YAML_FILE})
+ set(def_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR2_DEF_FILE})
+
+ set(fq_data_files "")
+ if(ADD_GEN_HDR2_DATA_FILES)
+ foreach(data_file IN LISTS ADD_GEN_HDR2_DATA_FILES)
+ list(APPEND fq_data_files "${CMAKE_CURRENT_SOURCE_DIR}/${data_file}")
+ endforeach(data_file)
+ endif()
+
+ set(entry_points "${TARGET_ENTRYPOINT_NAME_LIST}")
+ list(TRANSFORM entry_points PREPEND "--e=")
+
+ add_custom_command(
+ OUTPUT ${out_file}
+ COMMAND ${Python3_EXECUTABLE} ${LIBC_SOURCE_DIR}/newhdrgen/yaml_to_classes.py
+ ${yaml_file}
+ --h_def_file ${def_file}
+ ${entry_points}
+ --output_dir ${out_file}
+ DEPENDS ${yaml_file} ${def_file} ${fq_data_files}
+ COMMENT "Generating header ${ADD_GEN_HDR2_GE2N_HDR} from ${yaml_file} and ${def_file}"
+ )
+ if(LIBC_TARGET_OS_IS_GPU)
+ file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls)
+ file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls/gpu)
+ set(decl_out_file ${LIBC_INCLUDE_DIR}/llvm-libc-decls/${relative_path})
+ add_custom_command(
+ OUTPUT ${decl_out_file}
+ COMMAND ${Python3_EXECUTABLE} ${LIBC_SOURCE_DIR}/newhdrgen/yaml_to_classes.py
+ ${yaml_file}
+ --export-decls
+ ${entry_points}
+ --output_dir ${decl_out_file}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ DEPENDS ${yaml_file} ${fq_data_files}
+ )
+ endif()
+
+ if(ADD_GEN_HDR2_DEPENDS)
+ get_fq_deps_list(fq_deps_list ${ADD_GEN_HDR2_DEPENDS})
+ # Dependencies of a add_header target can only be another add_gen_header target
+ # or an add_header target.
+ foreach(dep IN LISTS fq_deps_list)
+ get_target_property(header_file ${dep} HEADER_FILE_PATH)
+ if(NOT header_file)
+ message(FATAL_ERROR "Invalid dependency '${dep}' for '${fq_target_name}'.")
+ endif()
+ endforeach()
+ endif()
+ set(generated_hdr_target ${fq_target_name}.__generated_hdr__)
+ add_custom_target(
+ ${generated_hdr_target}
+ DEPENDS ${out_file} ${fq_deps_list} ${decl_out_file}
+ )
+
+ add_header_library(
+ ${target_name}
+ HDRS
+ ${out_file}
+ )
+
+ add_dependencies(${fq_target_name} ${generated_hdr_target})
+
+ set_target_properties(
+ ${fq_target_name}
+ PROPERTIES
+ HEADER_FILE_PATH ${out_file}
+ DECLS_FILE_PATH "${decl_out_file}"
+ DEPS "${fq_deps_list}"
+ )
+
+
+endfunction(add_gen_header2)
+
# Usage:
# add_gen_header(
# <target name>
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index a10dec0..320f3e9 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -267,5 +267,5 @@ def SearchAPI : PublicAPI<"search.h"> {
}
def SysStatvfsAPI : PublicAPI<"sys/statvfs.h"> {
- let Types = ["fsblkcnt_t", "fsfilcnt_t", "struct statvfs"];
+ let Types = ["struct statvfs"];
}
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index 8a52d80e..0294f62 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -45,8 +45,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.sys_select
libc.include.sys_socket
libc.include.sys_stat
- # statvfs is broken, will uncomment once it's fixed.
- # libc.include.sys_statvfs
+ libc.include.sys_statvfs
libc.include.sys_syscall
libc.include.sys_time
libc.include.sys_types
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 2cf7206..37cae19 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -17,18 +17,41 @@ add_header(
__llvm-libc-common.h
)
-add_gen_header(
+macro(add_header_macro TARGET_NAME YAML_FILE DEF_FILE GEN_HDR DEPENDS)
+ if (LIBC_USE_NEW_HEADER_GEN)
+ add_gen_header2(
+ ${TARGET_NAME}
+ YAML_FILE ${YAML_FILE}
+ DEF_FILE ${DEF_FILE}
+ GEN_HDR ${GEN_HDR}
+ ${DEPENDS}
+ ${ARGN}
+ )
+ else()
+ add_gen_header(
+ ${TARGET_NAME}
+ DEF_FILE ${DEF_FILE}
+ GEN_HDR ${GEN_HDR}
+ ${DEPENDS}
+ ${ARGN}
+ )
+ endif()
+endmacro()
+
+add_header_macro(
ctype
- DEF_FILE ctype.h.def
- GEN_HDR ctype.h
+ ../libc/newhdrgen/yaml/ctype.yaml
+ ctype.h.def
+ ctype.h
DEPENDS
.llvm_libc_common_h
)
-add_gen_header(
+add_header_macro(
dirent
- DEF_FILE dirent.h.def
- GEN_HDR dirent.h
+ ../libc/newhdrgen/yaml/dirent.yaml
+ dirent.h.def
+ dirent.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.ino_t
@@ -36,10 +59,11 @@ add_gen_header(
.llvm-libc-types.struct_dirent
)
-add_gen_header(
+add_header_macro(
fcntl
- DEF_FILE fcntl.h.def
- GEN_HDR fcntl.h
+ ../libc/newhdrgen/yaml/fcntl.yaml
+ fcntl.h.def
+ fcntl.h
DEPENDS
.llvm-libc-macros.fcntl_macros
.llvm-libc-types.mode_t
@@ -51,28 +75,31 @@ add_gen_header(
.llvm_libc_common_h
)
-add_gen_header(
+add_header_macro(
dlfcn
- DEF_FILE dlfcn.h.def
- GEN_HDR dlfcn.h
+ ../libc/newhdrgen/yaml/dlfcn.yaml
+ dlfcn.h.def
+ dlfcn.h
DEPENDS
.llvm-libc-macros.dlfcn_macros
.llvm_libc_common_h
)
-add_gen_header(
+add_header_macro(
features
- DEF_FILE features.h.def
- GEN_HDR features.h
+ ../libc/newhdrgen/yaml/features.yaml
+ features.h.def
+ features.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.features_macros
)
-add_gen_header(
+add_header_macro(
fenv
- DEF_FILE fenv.h.def
- GEN_HDR fenv.h
+ ../libc/newhdrgen/yaml/fenv.yaml
+ fenv.h.def
+ fenv.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.fenv_macros
@@ -80,44 +107,49 @@ add_gen_header(
.llvm-libc-types.fexcept_t
)
-add_gen_header(
+add_header_macro(
inttypes
- DEF_FILE inttypes.h.def
- GEN_HDR inttypes.h
+ ../libc/newhdrgen/yaml/inttypes.yaml
+ inttypes.h.def
+ inttypes.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.imaxdiv_t
.llvm-libc-macros.inttypes_macros
)
-add_gen_header(
+add_header_macro(
float
- DEF_FILE float.h.def
- GEN_HDR float.h
+ ../libc/newhdrgen/yaml/float.yaml
+ float.h.def
+ float.h
DEPENDS
.llvm-libc-macros.float_macros
)
-add_gen_header(
+add_header_macro(
stdint
- DEF_FILE stdint.h.def
- GEN_HDR stdint.h
+ ../libc/newhdrgen/yaml/stdint.yaml
+ stdint.h.def
+ stdint.h
DEPENDS
.llvm-libc-macros.stdint_macros
)
-add_gen_header(
+add_header_macro(
limits
- DEF_FILE limits.h.def
- GEN_HDR limits.h
+ ../libc/newhdrgen/yaml/limits.yaml
+ limits.h.def
+ limits.h
DEPENDS
.llvm-libc-macros.limits_macros
)
-add_gen_header(
+add_header_macro(
math
- DEF_FILE math.h.def
- GEN_HDR math.h
+ ../libc/newhdrgen/yaml/math.yaml
+ math.h.def
+ math.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.float16_macros
@@ -128,10 +160,11 @@ add_gen_header(
.llvm-libc-types.float128
)
-add_gen_header(
+add_header_macro(
stdfix
- DEF_FILE stdfix.h.def
- GEN_HDR stdfix.h
+ ../libc/newhdrgen/yaml/stdfix.yaml
+ stdfix.h.def
+ stdfix.h
DEPENDS
.llvm-libc-macros.stdfix_macros
)
@@ -139,55 +172,61 @@ add_gen_header(
# TODO: This should be conditional on POSIX networking being included.
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/arpa)
-add_gen_header(
+add_header_macro(
arpa_inet
- DEF_FILE arpa/inet.h.def
- GEN_HDR arpa/inet.h
+ ../libc/newhdrgen/yaml/arpa/inet.yaml
+ arpa/inet.h.def
+ arpa/inet.h
DEPENDS
.llvm_libc_common_h
)
-add_gen_header(
+add_header_macro(
assert
- DEF_FILE assert.h.def
- GEN_HDR assert.h
+ ../libc/newhdrgen/yaml/assert.yaml
+ assert.h.def
+ assert.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.assert_macros
)
-add_gen_header(
+add_header_macro(
setjmp
- DEF_FILE setjmp.h.def
- GEN_HDR setjmp.h
+ ../libc/newhdrgen/yaml/setjmp.yaml
+ setjmp.h.def
+ setjmp.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.jmp_buf
)
-add_gen_header(
+add_header_macro(
string
- DEF_FILE string.h.def
- GEN_HDR string.h
+ ../libc/newhdrgen/yaml/string.yaml
+ string.h.def
+ string.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.null_macro
.llvm-libc-types.size_t
)
-add_gen_header(
+add_header_macro(
strings
- DEF_FILE strings.h.def
- GEN_HDR strings.h
+ ../libc/newhdrgen/yaml/strings.yaml
+ strings.h.def
+ strings.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.size_t
)
-add_gen_header(
+add_header_macro(
search
- DEF_FILE search.h.def
- GEN_HDR search.h
+ ../libc/newhdrgen/yaml/search.yaml
+ search.h.def
+ search.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.ACTION
@@ -196,10 +235,11 @@ add_gen_header(
.llvm-libc-types.size_t
)
-add_gen_header(
+add_header_macro(
time
- DEF_FILE time.h.def
- GEN_HDR time.h
+ ../libc/newhdrgen/yaml/time.yaml
+ time.h.def
+ time.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.time_macros
@@ -211,10 +251,11 @@ add_gen_header(
.llvm-libc-types.clockid_t
)
-add_gen_header(
+add_header_macro(
threads
- DEF_FILE threads.h.def
- GEN_HDR threads.h
+ ../libc/newhdrgen/yaml/threads.yaml
+ threads.h.def
+ threads.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.__call_once_func_t
@@ -227,19 +268,21 @@ add_gen_header(
.llvm-libc-types.tss_dtor_t
)
-add_gen_header(
+add_header_macro(
errno
- DEF_FILE errno.h.def
- GEN_HDR errno.h
+ ../libc/newhdrgen/yaml/errno.yaml
+ errno.h.def
+ errno.h
DEPENDS
.llvm-libc-macros.generic_error_number_macros
.llvm-libc-macros.error_number_macros
)
-add_gen_header(
+add_header_macro(
signal
- DEF_FILE signal.h.def
- GEN_HDR signal.h
+ ../libc/newhdrgen/yaml/signal.yaml
+ signal.h.def
+ signal.h
DEPENDS
.llvm-libc-macros.signal_macros
.llvm-libc-types.sig_atomic_t
@@ -251,28 +294,31 @@ add_gen_header(
.llvm-libc-types.pid_t
)
-add_gen_header(
+add_header_macro(
stdbit
- DEF_FILE stdbit.h.def
- GEN_HDR stdbit.h
+ ../libc/newhdrgen/yaml/stdbit.yaml
+ stdbit.h.def
+ stdbit.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.stdbit_macros
)
-add_gen_header(
+add_header_macro(
stdckdint
- DEF_FILE stdckdint.h.def
- GEN_HDR stdckdint.h
+ ../libc/newhdrgen/yaml/stdckdint.yaml
+ stdckdint.h.def
+ stdckdint.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.stdckdint_macros
)
-add_gen_header(
+add_header_macro(
stdio
- DEF_FILE stdio.h.def
- GEN_HDR stdio.h
+ ../libc/newhdrgen/yaml/stdio.yaml
+ stdio.h.def
+ stdio.h
DEPENDS
.llvm-libc-macros.file_seek_macros
.llvm-libc-macros.stdio_macros
@@ -284,10 +330,11 @@ add_gen_header(
.llvm_libc_common_h
)
-add_gen_header(
+add_header_macro(
stdlib
- DEF_FILE stdlib.h.def
- GEN_HDR stdlib.h
+ ../libc/newhdrgen/yaml/stdlib.yaml
+ stdlib.h.def
+ stdlib.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.stdlib_macros
@@ -301,10 +348,11 @@ add_gen_header(
.llvm-libc-types.__atexithandler_t
)
-add_gen_header(
+add_header_macro(
unistd
- DEF_FILE unistd.h.def
- GEN_HDR unistd.h
+ ../libc/newhdrgen/yaml/unistd.yaml
+ unistd.h.def
+ unistd.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.file_seek_macros
@@ -319,10 +367,11 @@ add_gen_header(
.llvm-libc-types.__getoptargv_t
)
-add_gen_header(
+add_header_macro(
pthread
- DEF_FILE pthread.h.def
- GEN_HDR pthread.h
+ ../libc/newhdrgen/yaml/pthread.yaml
+ pthread.h.def
+ pthread.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.__atfork_callback_t
@@ -340,10 +389,11 @@ add_gen_header(
.llvm-libc-types.pthread_t
)
-add_gen_header(
+add_header_macro(
sched
- DEF_FILE sched.h.def
- GEN_HDR sched.h
+ ../libc/newhdrgen/yaml/sched.yaml
+ sched.h.def
+ sched.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sched_macros
@@ -356,10 +406,11 @@ add_gen_header(
.llvm-libc-types.struct_timespec
)
-add_gen_header(
+add_header_macro(
spawn
- DEF_FILE spawn.h.def
- GEN_HDR spawn.h
+ ../libc/newhdrgen/yaml/spawn.yaml
+ spawn.h.def
+ spawn.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.mode_t
@@ -373,19 +424,21 @@ add_gen_header(
# them.
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/sys)
-add_gen_header(
+add_header_macro(
sys_auxv
- DEF_FILE sys/auxv.h.def
- GEN_HDR sys/auxv.h
+ ../libc/newhdrgen/yaml/sys/auxv.yaml
+ sys/auxv.h.def
+ sys/auxv.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_auxv_macros
)
-add_gen_header(
+add_header_macro(
sys_epoll
- DEF_FILE sys/epoll.h.def
- GEN_HDR sys/epoll.h
+ ../libc/newhdrgen/yaml/sys/epoll.yaml
+ sys/epoll.h.def
+ sys/epoll.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.struct_epoll_event
@@ -394,19 +447,21 @@ add_gen_header(
.llvm-libc-macros.sys_epoll_macros
)
-add_gen_header(
+add_header_macro(
sys_ioctl
- DEF_FILE sys/ioctl.h.def
- GEN_HDR sys/ioctl.h
+ ../libc/newhdrgen/yaml/sys/ioctl.yaml
+ sys/ioctl.h.def
+ sys/ioctl.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_ioctl_macros
)
-add_gen_header(
+add_header_macro(
sys_mman
- DEF_FILE sys/mman.h.def
- GEN_HDR sys/mman.h
+ ../libc/newhdrgen/yaml/sys/mman.yaml
+ sys/mman.h.def
+ sys/mman.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_mman_macros
@@ -415,10 +470,11 @@ add_gen_header(
.llvm-libc-types.ssize_t
)
-add_gen_header(
+add_header_macro(
sys_prctl
- DEF_FILE sys/prctl.h.def
- GEN_HDR sys/prctl.h
+ ../libc/newhdrgen/yaml/sys/prctl.yaml
+ sys/prctl.h.def
+ sys/prctl.h
DEPENDS
.llvm_libc_common_h
)
@@ -431,10 +487,11 @@ add_header(
.llvm-libc-macros.sys_queue_macros
)
-add_gen_header(
+add_header_macro(
sys_random
- DEF_FILE sys/random.h.def
- GEN_HDR sys/random.h
+ ../libc/newhdrgen/yaml/sys/random.yaml
+ sys/random.h.def
+ sys/random.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_random_macros
@@ -442,10 +499,11 @@ add_gen_header(
.llvm-libc-types.ssize_t
)
-add_gen_header(
+add_header_macro(
sys_resource
- DEF_FILE sys/resource.h.def
- GEN_HDR sys/resource.h
+ ../libc/newhdrgen/yaml/sys/resource.yaml
+ sys/resource.h.def
+ sys/resource.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_resource_macros
@@ -453,10 +511,11 @@ add_gen_header(
.llvm-libc-types.struct_rlimit
)
-add_gen_header(
+add_header_macro(
sys_stat
- DEF_FILE sys/stat.h.def
- GEN_HDR sys/stat.h
+ ../libc/newhdrgen/yaml/sys/stat.yaml
+ sys/stat.h.def
+ sys/stat.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_stat_macros
@@ -474,10 +533,11 @@ add_gen_header(
.llvm-libc-types.struct_stat
)
-add_gen_header(
+add_header_macro(
sys_select
- DEF_FILE sys/select.h.def
- GEN_HDR sys/select.h
+ ../libc/newhdrgen/yaml/sys/select.yaml
+ sys/select.h.def
+ sys/select.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_select_macros
@@ -489,10 +549,11 @@ add_gen_header(
.llvm-libc-types.struct_timeval
)
-add_gen_header(
+add_header_macro(
sys_sendfile
- DEF_FILE sys/sendfile.h.def
- GEN_HDR sys/sendfile.h
+ ../libc/newhdrgen/yaml/sys/sendfile.yaml
+ sys/sendfile.h.def
+ sys/sendfile.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.off_t
@@ -500,10 +561,11 @@ add_gen_header(
.llvm-libc-types.ssize_t
)
-add_gen_header(
+add_header_macro(
sys_socket
- DEF_FILE sys/socket.h.def
- GEN_HDR sys/socket.h
+ ../libc/newhdrgen/yaml/sys/socket.yaml
+ sys/socket.h.def
+ sys/socket.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_socket_macros
@@ -513,35 +575,40 @@ add_gen_header(
.llvm-libc-types.struct_sockaddr_un
)
-add_gen_header(
+add_header_macro(
sys_statvfs
- DEF_FILE sys/statvfs.h.def
- GEN_HDR sys/statvfs.h
+ ../libc/newhdrgen/yaml/sys/statvfs.yaml
+ sys/statvfs.h.def
+ sys/statvfs.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.struct_statvfs
)
-add_gen_header(
+add_header_macro(
sys_syscall
- DEF_FILE sys/syscall.h.def
- GEN_HDR sys/syscall.h
+ ../libc/newhdrgen/yaml/sys/syscall.yaml
+ sys/syscall.h.def
+ sys/syscall.h
+ DEPENDS
)
-add_gen_header(
+add_header_macro(
sys_time
- DEF_FILE sys/time.h.def
- GEN_HDR sys/time.h
+ ../libc/newhdrgen/yaml/sys/time.yaml
+ sys/time.h.def
+ sys/time.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.struct_timeval
.llvm-libc-macros.sys_time_macros
)
-add_gen_header(
+add_header_macro(
sys_types
- DEF_FILE sys/types.h.def
- GEN_HDR sys/types.h
+ ../libc/newhdrgen/yaml/sys/types.yaml
+ sys/types.h.def
+ sys/types.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.blkcnt_t
@@ -567,19 +634,21 @@ add_gen_header(
.llvm-libc-types.uid_t
)
-add_gen_header(
+add_header_macro(
sys_utsname
- DEF_FILE sys/utsname.h.def
- GEN_HDR sys/utsname.h
+ ../libc/newhdrgen/yaml/sys/utsname.yaml
+ sys/utsname.h.def
+ sys/utsname.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.struct_utsname
)
-add_gen_header(
+add_header_macro(
sys_wait
- DEF_FILE sys/wait.h.def
- GEN_HDR sys/wait.h
+ ../libc/newhdrgen/yaml/sys/wait.yaml
+ sys/wait.h.def
+ sys/wait.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_wait_macros
@@ -588,10 +657,11 @@ add_gen_header(
.llvm-libc-types.siginfo_t
)
-add_gen_header(
+add_header_macro(
termios
- DEF_FILE termios.h.def
- GEN_HDR termios.h
+ ../libc/newhdrgen/yaml/termios.yaml
+ termios.h.def
+ termios.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.termios_macros
@@ -602,10 +672,11 @@ add_gen_header(
.llvm-libc-types.tcflag_t
)
-add_gen_header(
+add_header_macro(
uchar
- DEF_FILE uchar.h.def
- GEN_HDR uchar.h
+ ../libc/newhdrgen/yaml/uchar.yaml
+ uchar.h.def
+ uchar.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.mbstate_t
@@ -614,10 +685,11 @@ add_gen_header(
.llvm-libc-types.char32_t
)
-add_gen_header(
+add_header_macro(
wchar
- DEF_FILE wchar.h.def
- GEN_HDR wchar.h
+ ../libc/newhdrgen/yaml/wchar.yaml
+ wchar.h.def
+ wchar.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.wchar_macros
@@ -630,10 +702,11 @@ add_gen_header(
if(LIBC_TARGET_OS_IS_GPU)
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/gpu)
- add_gen_header(
+ add_header_macro(
gpu_rpc
- DEF_FILE gpu/rpc.h.def
- GEN_HDR gpu/rpc.h
+ ../libc/newhdrgen/yaml/gpu/rpc.yaml
+ gpu/rpc.h.def
+ gpu/rpc.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.rpc_opcodes_t
diff --git a/libc/newhdrgen/class_implementation/classes/include.py b/libc/newhdrgen/class_implementation/classes/include.py
deleted file mode 100644
index 2657f2e..0000000
--- a/libc/newhdrgen/class_implementation/classes/include.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python
-#
-# ====-- Include class for libc function headers --------------*- python -*--==#
-#
-# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-# See https://llvm.org/LICENSE.txt for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#
-# ==-------------------------------------------------------------------------==#
-
-
-class Include:
- def __init__(self, name):
- self.name = name
-
- def __str__(self):
- return f'#include "{self.name}"'
diff --git a/libc/newhdrgen/gpu_headers.py b/libc/newhdrgen/gpu_headers.py
index cc13096..d123e4a 100644
--- a/libc/newhdrgen/gpu_headers.py
+++ b/libc/newhdrgen/gpu_headers.py
@@ -17,7 +17,6 @@ class GpuHeaderFile:
self.enumerations = []
self.objects = []
self.functions = []
- self.includes = []
def add_macro(self, macro):
self.macros.append(macro)
diff --git a/libc/newhdrgen/header.py b/libc/newhdrgen/header.py
index 141e3c9..7ec2dee 100644
--- a/libc/newhdrgen/header.py
+++ b/libc/newhdrgen/header.py
@@ -17,7 +17,6 @@ class HeaderFile:
self.enumerations = []
self.objects = []
self.functions = []
- self.includes = []
def add_macro(self, macro):
self.macros.append(macro)
@@ -34,15 +33,9 @@ class HeaderFile:
def add_function(self, function):
self.functions.append(function)
- def add_include(self, include):
- self.includes.append(include)
-
def __str__(self):
content = [""]
- for include in self.includes:
- content.append(str(include))
-
for macro in self.macros:
content.append(f"{macro}\n")
diff --git a/libc/newhdrgen/yaml/arpa/arpa_inet.yaml b/libc/newhdrgen/yaml/arpa/inet.yaml
index c01235d..c01235d 100644
--- a/libc/newhdrgen/yaml/arpa/arpa_inet.yaml
+++ b/libc/newhdrgen/yaml/arpa/inet.yaml
diff --git a/libc/newhdrgen/yaml/gpu/gpu_rpc.yaml b/libc/newhdrgen/yaml/gpu/rpc.yaml
index 8a096db..8a096db 100644
--- a/libc/newhdrgen/yaml/gpu/gpu_rpc.yaml
+++ b/libc/newhdrgen/yaml/gpu/rpc.yaml
diff --git a/libc/newhdrgen/yaml/math.yaml b/libc/newhdrgen/yaml/math.yaml
index 8588389b..ce562c6 100644
--- a/libc/newhdrgen/yaml/math.yaml
+++ b/libc/newhdrgen/yaml/math.yaml
@@ -64,8 +64,6 @@ functions:
return_type: double
arguments:
- type: double
- attributes:
- - __LIBC_CONST_ATTR
- name: fabsf
standards:
- stdc
@@ -364,6 +362,20 @@ functions:
arguments:
- type: double
- type: double
+ - name: fmull
+ standards:
+ - stdc
+ return_type: float
+ arguments:
+ - type: long double
+ - type: long double
+ - name: dmull
+ standards:
+ - stdc
+ return_type: double
+ arguments:
+ - type: long double
+ - type: long double
- name: frexp
standards:
- stdc
@@ -1323,6 +1335,30 @@ functions:
- type: long double
- type: long double
guard: LIBC_TYPES_HAS_FLOAT16
+ - name: f16mul
+ standards:
+ - llvm_libc_ext
+ return_type: _Float16
+ arguments:
+ - type: double
+ - type: double
+ guard: LIBC_TYPES_HAS_FLOAT16
+ - name: f16mulf
+ standards:
+ - llvm_libc_ext
+ return_type: _Float16
+ arguments:
+ - type: float
+ - type: float
+ guard: LIBC_TYPES_HAS_FLOAT16
+ - name: f16mull
+ standards:
+ - llvm_libc_ext
+ return_type: _Float16
+ arguments:
+ - type: long double
+ - type: long double
+ guard: LIBC_TYPES_HAS_FLOAT16
- name: f16sqrt
standards:
- llvm_libc_ext
@@ -1756,6 +1792,14 @@ functions:
- type: float128
- type: float128
guard: LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128
+ - name: f16mulf128
+ standards:
+ - stdc
+ return_type: _Float16
+ arguments:
+ - type: float128
+ - type: float128
+ guard: LIBC_TYPES_HAS_FLOAT16_AND_FLOAT128
- name: f16sqrtf128
standards:
- llvm_libc_ext
@@ -1896,6 +1940,22 @@ functions:
- type: float128
- type: float128
guard: LIBC_TYPES_HAS_FLOAT128
+ - name: fmulf128
+ standards:
+ - llvm_libc_ext
+ return_type: float
+ arguments:
+ - type: float128
+ - type: float128
+ guard: LIBC_TYPES_HAS_FLOAT128
+ - name: dmulf128
+ standards:
+ - llvm_libc_ext
+ return_type: double
+ arguments:
+ - type: float128
+ - type: float128
+ guard: LIBC_TYPES_HAS_FLOAT128
- name: frexpf128
standards:
- stdc
diff --git a/libc/newhdrgen/yaml/sys/sys_auxv.yaml b/libc/newhdrgen/yaml/sys/auxv.yaml
index 072f63b..072f63b 100644
--- a/libc/newhdrgen/yaml/sys/sys_auxv.yaml
+++ b/libc/newhdrgen/yaml/sys/auxv.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_epoll.yaml b/libc/newhdrgen/yaml/sys/epoll.yaml
index 18d8f59..18d8f59 100644
--- a/libc/newhdrgen/yaml/sys/sys_epoll.yaml
+++ b/libc/newhdrgen/yaml/sys/epoll.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_ioctl.yaml b/libc/newhdrgen/yaml/sys/ioctl.yaml
index ffe73a8..ffe73a8 100644
--- a/libc/newhdrgen/yaml/sys/sys_ioctl.yaml
+++ b/libc/newhdrgen/yaml/sys/ioctl.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml
index c465f6b..c465f6b 100644
--- a/libc/newhdrgen/yaml/sys/sys_mman.yaml
+++ b/libc/newhdrgen/yaml/sys/mman.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_prctl.yaml b/libc/newhdrgen/yaml/sys/prctl.yaml
index 82374be..82374be 100644
--- a/libc/newhdrgen/yaml/sys/sys_prctl.yaml
+++ b/libc/newhdrgen/yaml/sys/prctl.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_random.yaml b/libc/newhdrgen/yaml/sys/random.yaml
index 6d84056..6d84056 100644
--- a/libc/newhdrgen/yaml/sys/sys_random.yaml
+++ b/libc/newhdrgen/yaml/sys/random.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_resource.yaml b/libc/newhdrgen/yaml/sys/resource.yaml
index 2cc801c..2cc801c 100644
--- a/libc/newhdrgen/yaml/sys/sys_resource.yaml
+++ b/libc/newhdrgen/yaml/sys/resource.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_select.yaml b/libc/newhdrgen/yaml/sys/select.yaml
index eb621f7..eb621f7 100644
--- a/libc/newhdrgen/yaml/sys/sys_select.yaml
+++ b/libc/newhdrgen/yaml/sys/select.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_sendfile.yaml b/libc/newhdrgen/yaml/sys/sendfile.yaml
index 8743bf0..8743bf0 100644
--- a/libc/newhdrgen/yaml/sys/sys_sendfile.yaml
+++ b/libc/newhdrgen/yaml/sys/sendfile.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_socket.yaml b/libc/newhdrgen/yaml/sys/socket.yaml
index f9984c6..f9984c6 100644
--- a/libc/newhdrgen/yaml/sys/sys_socket.yaml
+++ b/libc/newhdrgen/yaml/sys/socket.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_stat.yaml b/libc/newhdrgen/yaml/sys/stat.yaml
index 6ae69b4..6ae69b4 100644
--- a/libc/newhdrgen/yaml/sys/sys_stat.yaml
+++ b/libc/newhdrgen/yaml/sys/stat.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_statvfs.yaml b/libc/newhdrgen/yaml/sys/statvfs.yaml
index 3651901..5366677 100644
--- a/libc/newhdrgen/yaml/sys/sys_statvfs.yaml
+++ b/libc/newhdrgen/yaml/sys/statvfs.yaml
@@ -2,6 +2,8 @@ header: sys-statvfs.h
macros: []
types:
- type_name: struct_statvfs
+ - type_name: fsblkcnt_t
+ - type_name: fsfilcnt_t
enums: []
objects: []
functions:
diff --git a/libc/newhdrgen/yaml/sys/sys_syscall.yaml b/libc/newhdrgen/yaml/sys/syscall.yaml
index c0a64338..c0a64338 100644
--- a/libc/newhdrgen/yaml/sys/sys_syscall.yaml
+++ b/libc/newhdrgen/yaml/sys/syscall.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_time.yaml b/libc/newhdrgen/yaml/sys/time.yaml
index eb3dd54..eb3dd54 100644
--- a/libc/newhdrgen/yaml/sys/sys_time.yaml
+++ b/libc/newhdrgen/yaml/sys/time.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_types.yaml b/libc/newhdrgen/yaml/sys/types.yaml
index 15eaf10..15eaf10 100644
--- a/libc/newhdrgen/yaml/sys/sys_types.yaml
+++ b/libc/newhdrgen/yaml/sys/types.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_utsname.yaml b/libc/newhdrgen/yaml/sys/utsname.yaml
index c48f7e3..c48f7e3 100644
--- a/libc/newhdrgen/yaml/sys/sys_utsname.yaml
+++ b/libc/newhdrgen/yaml/sys/utsname.yaml
diff --git a/libc/newhdrgen/yaml/sys/sys_wait.yaml b/libc/newhdrgen/yaml/sys/wait.yaml
index 2f2f70d..2f2f70d 100644
--- a/libc/newhdrgen/yaml/sys/sys_wait.yaml
+++ b/libc/newhdrgen/yaml/sys/wait.yaml
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index 205bb35..7858805 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -16,7 +16,6 @@ from gpu_headers import GpuHeaderFile as GpuHeader
from class_implementation.classes.macro import Macro
from class_implementation.classes.type import Type
from class_implementation.classes.function import Function
-from class_implementation.classes.include import Include
from class_implementation.classes.enumeration import Enumeration
from class_implementation.classes.object import Object
@@ -103,9 +102,6 @@ def yaml_to_classes(yaml_data, header_class, entry_points=None):
Object(object_data["object_name"], object_data["object_type"])
)
- for include_data in yaml_data.get("includes", []):
- header.add_include(Include(include_data))
-
return header
diff --git a/libc/src/sys/statvfs/linux/CMakeLists.txt b/libc/src/sys/statvfs/linux/CMakeLists.txt
index a6660c0..2953717 100644
--- a/libc/src/sys/statvfs/linux/CMakeLists.txt
+++ b/libc/src/sys/statvfs/linux/CMakeLists.txt
@@ -8,7 +8,7 @@ add_header_library(
libc.src.__support.common
libc.src.__support.CPP.optional
libc.include.sys_syscall
- libc.include.llvm-libc-types.struct_statvfs
+ libc.include.sys_statvfs
)
add_entrypoint_object(
@@ -19,7 +19,7 @@ add_entrypoint_object(
../statvfs.h
DEPENDS
libc.src.__support.libc_assert
- libc.include.llvm-libc-types.struct_statvfs
+ libc.include.sys_statvfs
.statfs_utils
)
@@ -31,7 +31,7 @@ add_entrypoint_object(
../fstatvfs.h
DEPENDS
libc.src.__support.libc_assert
- libc.include.llvm-libc-types.struct_statvfs
+ libc.include.sys_statvfs
.statfs_utils
)
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index e74b022..be0415d 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -1,5 +1,5 @@
if(LIBC_TESTS_CAN_USE_MPFR)
- add_library(libcMPFRWrapper
+ add_library(libcMPFRWrapper STATIC
MPFRUtils.cpp
MPFRUtils.h
mpfr_inc.h
diff --git a/libcxx/benchmarks/CMakeLists.txt b/libcxx/benchmarks/CMakeLists.txt
index 1106726..d96ccc1 100644
--- a/libcxx/benchmarks/CMakeLists.txt
+++ b/libcxx/benchmarks/CMakeLists.txt
@@ -135,6 +135,7 @@ set(BENCHMARK_TESTS
algorithms/ranges_sort.bench.cpp
algorithms/ranges_sort_heap.bench.cpp
algorithms/ranges_stable_sort.bench.cpp
+ algorithms/set_intersection.bench.cpp
algorithms/sort.bench.cpp
algorithms/sort_heap.bench.cpp
algorithms/stable_sort.bench.cpp
diff --git a/libcxx/benchmarks/algorithms/set_intersection.bench.cpp b/libcxx/benchmarks/algorithms/set_intersection.bench.cpp
new file mode 100644
index 0000000..b3fb15f
--- /dev/null
+++ b/libcxx/benchmarks/algorithms/set_intersection.bench.cpp
@@ -0,0 +1,184 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <algorithm>
+#include <cstdlib>
+#include <iterator>
+#include <set>
+#include <vector>
+
+#include "common.h"
+#include "test_iterators.h"
+
+namespace {
+
+// types of containers we'll want to test, covering interesting iterator types
+struct VectorContainer {
+ template <typename... Args>
+ using type = std::vector<Args...>;
+
+ static constexpr const char* Name = "Vector";
+};
+
+struct SetContainer {
+ template <typename... Args>
+ using type = std::set<Args...>;
+
+ static constexpr const char* Name = "Set";
+};
+
+using AllContainerTypes = std::tuple<VectorContainer, SetContainer>;
+
+// set_intersection performance may depend on where matching values lie
+enum class OverlapPosition {
+ None,
+ Front,
+ // performance-wise, matches at the back are identical to ones at the front
+ Interlaced,
+};
+
+struct AllOverlapPositions : EnumValuesAsTuple<AllOverlapPositions, OverlapPosition, 3> {
+ static constexpr const char* Names[] = {"None", "Front", "Interlaced"};
+};
+
+// forward_iterator wrapping which, for each increment, moves the underlying iterator forward Stride elements
+template <typename Wrapped>
+struct StridedFwdIt {
+ Wrapped base_;
+ unsigned stride_;
+
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = typename Wrapped::difference_type;
+ using value_type = typename Wrapped::value_type;
+ using pointer = typename Wrapped::pointer;
+ using reference = typename Wrapped::reference;
+
+ StridedFwdIt(Wrapped base, unsigned stride) : base_(base), stride_(stride) { assert(stride_ != 0); }
+
+ StridedFwdIt operator++() {
+ for (unsigned i = 0; i < stride_; ++i)
+ ++base_;
+ return *this;
+ }
+ StridedFwdIt operator++(int) {
+ auto tmp = *this;
+ ++*this;
+ return tmp;
+ }
+ value_type& operator*() { return *base_; }
+ const value_type& operator*() const { return *base_; }
+ value_type& operator->() { return *base_; }
+ const value_type& operator->() const { return *base_; }
+ bool operator==(const StridedFwdIt& o) const { return base_ == o.base_; }
+ bool operator!=(const StridedFwdIt& o) const { return !operator==(o); }
+};
+template <typename Wrapped>
+StridedFwdIt(Wrapped, unsigned) -> StridedFwdIt<Wrapped>;
+
+template <typename T>
+std::vector<T> getVectorOfRandom(size_t N) {
+ std::vector<T> v;
+ fillValues(v, N, Order::Random);
+ sortValues(v, Order::Random);
+ return std::vector<T>(v);
+}
+
+// Realistically, data won't all be nicely contiguous in a container,
+// we'll go through some effort to ensure that it's shuffled through memory
+// this is especially important for containers with non-contiguous element
+// storage, but it will affect even a std::vector, because when you copy a
+// std::vector<std::string> the underlying data storage position for the char
+// arrays of the copy are likely to have high locality
+template <class Container>
+std::pair<Container, Container> genCacheUnfriendlyData(size_t size1, size_t size2, OverlapPosition pos) {
+ using ValueType = typename Container::value_type;
+ auto move_into = [](auto first, auto last) {
+ Container out;
+ std::move(first, last, std::inserter(out, out.begin()));
+ return out;
+ };
+ const auto src_size = pos == OverlapPosition::None ? size1 + size2 : std::max(size1, size2);
+ std::vector<ValueType> src = getVectorOfRandom<ValueType>(src_size);
+
+ if (pos == OverlapPosition::None) {
+ std::sort(src.begin(), src.end());
+ return std::make_pair(move_into(src.begin(), src.begin() + size1), move_into(src.begin() + size1, src.end()));
+ }
+
+ // All other overlap types will have to copy some part of the data, but if
+ // we copy after sorting it will likely have high locality, so we sort
+ // each copy separately
+ auto copy = src;
+ std::sort(src.begin(), src.end());
+ std::sort(copy.begin(), copy.end());
+
+ switch (pos) {
+ case OverlapPosition::None:
+ // we like -Wswitch :)
+ break;
+
+ case OverlapPosition::Front:
+ return std::make_pair(move_into(src.begin(), src.begin() + size1), move_into(copy.begin(), copy.begin() + size2));
+
+ case OverlapPosition::Interlaced:
+ const auto stride1 = size1 < size2 ? size2 / size1 : 1;
+ const auto stride2 = size2 < size1 ? size1 / size2 : 1;
+ return std::make_pair(move_into(StridedFwdIt(src.begin(), stride1), StridedFwdIt(src.end(), stride1)),
+ move_into(StridedFwdIt(copy.begin(), stride2), StridedFwdIt(copy.end(), stride2)));
+ }
+ std::abort(); // would be std::unreachable() if it could
+ return std::pair<Container, Container>();
+}
+
+template <class ValueType, class Container, class Overlap>
+struct SetIntersection {
+ using ContainerType = typename Container::template type<Value<ValueType>>;
+ size_t size1_;
+ size_t size2_;
+
+ SetIntersection(size_t size1, size_t size2) : size1_(size1), size2_(size2) {}
+
+ bool skip() const noexcept {
+ // let's save some time and skip simmetrical runs
+ return size1_ < size2_;
+ }
+
+ void run(benchmark::State& state) const {
+ auto input = genCacheUnfriendlyData<ContainerType>(size1_, size2_, Overlap());
+ std::vector<Value<ValueType>> out(std::min(size1_, size2_));
+
+ const auto BATCH_SIZE = std::max(size_t{512}, (2 * TestSetElements) / (size1_ + size2_));
+ for (const auto& _ : state) {
+ while (state.KeepRunningBatch(BATCH_SIZE)) {
+ for (unsigned i = 0; i < BATCH_SIZE; ++i) {
+ const auto& [c1, c2] = input;
+ auto res = std::set_intersection(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin());
+ benchmark::DoNotOptimize(res);
+ }
+ }
+ }
+ }
+
+ std::string name() const {
+ return std::string("SetIntersection") + Overlap::name() + '_' + Container::Name + ValueType::name() + '_' +
+ std::to_string(size1_) + '_' + std::to_string(size2_);
+ }
+};
+
+} // namespace
+
+int main(int argc, char** argv) { /**/
+ benchmark::Initialize(&argc, argv);
+ if (benchmark::ReportUnrecognizedArguments(argc, argv))
+ return 1;
+
+ makeCartesianProductBenchmark<SetIntersection, AllValueTypes, AllContainerTypes, AllOverlapPositions>(
+ Quantities, Quantities);
+ benchmark::RunSpecifiedBenchmarks();
+ return 0;
+}
diff --git a/libcxx/cmake/caches/Apple.cmake b/libcxx/cmake/caches/Apple.cmake
index 1038f1a..8768653 100644
--- a/libcxx/cmake/caches/Apple.cmake
+++ b/libcxx/cmake/caches/Apple.cmake
@@ -15,3 +15,6 @@ set(LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "")
set(LIBCXXABI_ENABLE_ASSERTIONS OFF CACHE BOOL "")
set(LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST ON CACHE BOOL "")
set(LIBCXXABI_USE_LLVM_UNWINDER OFF CACHE BOOL "") # libunwind is built separately
+
+set(LIBCXX_TEST_CONFIG "apple-libc++-shared.cfg.in" CACHE STRING "")
+set(LIBCXXABI_TEST_CONFIG "apple-libc++abi-shared.cfg.in" CACHE STRING "")
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 53cfc37..b548322 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -346,7 +346,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_optional`` ``202110L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_out_ptr`` *unimplemented*
+ ``__cpp_lib_out_ptr`` ``202106L``
---------------------------------------------------------- -----------------
``__cpp_lib_print`` ``202207L``
---------------------------------------------------------- -----------------
@@ -450,7 +450,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_optional_range_support`` *unimplemented*
---------------------------------------------------------- -----------------
- ``__cpp_lib_out_ptr`` *unimplemented*
+ ``__cpp_lib_out_ptr`` ``202311L``
---------------------------------------------------------- -----------------
``__cpp_lib_philox_engine`` *unimplemented*
---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 624550f..784934e 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -38,6 +38,7 @@ What's New in Libc++ 19.0.0?
Implemented Papers
------------------
+- P1132R8 - ``out_ptr`` - a scalable output pointer abstraction
- P2637R3 - Member ``visit``
- P2652R2 - Disallow User Specialization of ``allocator_traits``
- P2819R2 - Add ``tuple`` protocol to ``complex``
@@ -71,6 +72,10 @@ Improvements and New Features
- The ``std::ranges::minmax`` algorithm has been optimized for integral types, resulting in a performance increase of
up to 100x.
+- The ``std::set_intersection`` and ``std::ranges::set_intersection`` algorithms have been optimized to fast-forward over
+ contiguous ranges of non-matching values, reducing the number of comparisons from linear to
+ logarithmic growth with the number of elements in best-case scenarios.
+
- The ``_LIBCPP_ENABLE_CXX26_REMOVED_STRSTREAM`` macro has been added to make the declarations in ``<strstream>`` available.
- The ``_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT`` macro has been added to make the declarations in ``<locale>``
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index cc601b3..547d38c 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -192,7 +192,7 @@
"`3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized", "November 2022","","",""
"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","|Complete|","18.0",""
"`3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators", "November 2022","","","|ranges|"
-"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","","",""
+"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","|Complete|","19.0",""
"`3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable", "November 2022","","","|ranges|"
"`3600 <https://wg21.link/LWG3600>`__","Making ``istream_iterator`` copy constructor trivial is an ABI break", "November 2022","","",""
"`3629 <https://wg21.link/LWG3629>`__","``make_error_code`` and ``make_error_condition`` are customization points","November 2022","|Complete|","16.0",""
@@ -282,7 +282,7 @@
"`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","February 2023","|Complete|","14.0",""
"`3655 <https://wg21.link/LWG3655>`__","The ``INVOKE`` operation and union types","February 2023","|Complete|","18.0",""
"`3723 <https://wg21.link/LWG3723>`__","``priority_queue::push_range`` needs to ``append_range``","February 2023","","","|ranges|"
-"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","","",""
+"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","|Complete|","19.0",""
"`3772 <https://wg21.link/LWG3772>`__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","February 2023","|Complete|","17.0","|ranges|"
"`3786 <https://wg21.link/LWG3786>`__","Flat maps' deduction guide needs to default ``Allocator`` to be useful","February 2023","","",""
"`3803 <https://wg21.link/LWG3803>`__","``flat_foo`` constructors taking ``KeyContainer`` lack ``KeyCompare`` parameter","February 2023","","",""
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 4f589cd..6dd6bda 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -13,7 +13,7 @@
"","","","","","",""
"`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","|Complete|","15.0"
"`P0448R4 <https://wg21.link/P0448R4>`__","LWG","A strstream replacement using span<charT> as buffer","June 2021","",""
-"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","",""
+"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","|Complete|","19.0"
"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","|Complete|","17.0"
"`P1425R4 <https://wg21.link/P1425R4>`__","LWG","Iterators pair constructors for stack and queue","June 2021","|Complete|","14.0","|ranges|"
"`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0"
diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index b5732ee..dec9af1 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -24,7 +24,7 @@
"`3749 <https://wg21.link/LWG3749>`__","``common_iterator`` should handle integer-class difference types","Kona November 2023","","",""
"`3809 <https://wg21.link/LWG3809>`__","Is ``std::subtract_with_carry_engine<uint16_t>`` supposed to work","Kona November 2023","","",""
"`3892 <https://wg21.link/LWG3892>`__","Incorrect formatting of nested ranges and tuples","Kona November 2023","|Complete|","17.0","|format|"
-"`3897 <https://wg21.link/LWG3897>`__","``inout_ptr`` will not update raw pointer to 0","Kona November 2023","","",""
+"`3897 <https://wg21.link/LWG3897>`__","``inout_ptr`` will not update raw pointer to 0","Kona November 2023","|Complete|","19.0",""
"`3946 <https://wg21.link/LWG3946>`__","The definition of ``const_iterator_t`` should be reworked","Kona November 2023","","",""
"`3947 <https://wg21.link/LWG3947>`__","Unexpected constraints on ``adjacent_transform_view::base()``","Kona November 2023","","","|ranges|"
"`3948 <https://wg21.link/LWG3948>`__","``possibly-const-range and as-const-pointer`` should be ``noexcept``","Kona November 2023","","","|ranges|"
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 26bad4f..4b036ec 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -533,6 +533,8 @@ set(files
__memory/concepts.h
__memory/construct_at.h
__memory/destruct_n.h
+ __memory/inout_ptr.h
+ __memory/out_ptr.h
__memory/pointer_traits.h
__memory/ranges_construct_at.h
__memory/ranges_uninitialized_algorithms.h
diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h
index 5cf13f0..8ced989 100644
--- a/libcxx/include/__algorithm/iterator_operations.h
+++ b/libcxx/include/__algorithm/iterator_operations.h
@@ -11,6 +11,7 @@
#include <__algorithm/iter_swap.h>
#include <__algorithm/ranges_iterator_concept.h>
+#include <__assert>
#include <__config>
#include <__iterator/advance.h>
#include <__iterator/distance.h>
@@ -160,6 +161,59 @@ struct _IterOps<_ClassicAlgPolicy> {
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 void __advance_to(_Iter& __first, _Iter __last) {
__first = __last;
}
+
+ // advance with sentinel, a la std::ranges::advance
+ template <class _Iter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_Iter>
+ __advance_to(_Iter& __iter, __difference_type<_Iter> __count, const _Iter& __sentinel) {
+ return _IterOps::__advance_to(__iter, __count, __sentinel, typename iterator_traits<_Iter>::iterator_category());
+ }
+
+private:
+ // advance with sentinel, a la std::ranges::advance -- InputIterator specialization
+ template <class _InputIter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_InputIter> __advance_to(
+ _InputIter& __iter, __difference_type<_InputIter> __count, const _InputIter& __sentinel, input_iterator_tag) {
+ __difference_type<_InputIter> __dist = 0;
+ for (; __dist < __count && __iter != __sentinel; ++__dist)
+ ++__iter;
+ return __count - __dist;
+ }
+
+ // advance with sentinel, a la std::ranges::advance -- BidirectionalIterator specialization
+ template <class _BiDirIter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_BiDirIter>
+ __advance_to(_BiDirIter& __iter,
+ __difference_type<_BiDirIter> __count,
+ const _BiDirIter& __sentinel,
+ bidirectional_iterator_tag) {
+ __difference_type<_BiDirIter> __dist = 0;
+ if (__count >= 0)
+ for (; __dist < __count && __iter != __sentinel; ++__dist)
+ ++__iter;
+ else
+ for (__count = -__count; __dist < __count && __iter != __sentinel; ++__dist)
+ --__iter;
+ return __count - __dist;
+ }
+
+ // advance with sentinel, a la std::ranges::advance -- RandomIterator specialization
+ template <class _RandIter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static __difference_type<_RandIter>
+ __advance_to(_RandIter& __iter,
+ __difference_type<_RandIter> __count,
+ const _RandIter& __sentinel,
+ random_access_iterator_tag) {
+ auto __dist = _IterOps::distance(__iter, __sentinel);
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __count == 0 || (__dist < 0) == (__count < 0), "__sentinel must precede __iter when __count < 0");
+ if (__count < 0)
+ __dist = __dist > __count ? __dist : __count;
+ else
+ __dist = __dist < __count ? __dist : __count;
+ __iter += __dist;
+ return __count - __dist;
+ }
};
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h
index 8fd355a..c417d84 100644
--- a/libcxx/include/__algorithm/lower_bound.h
+++ b/libcxx/include/__algorithm/lower_bound.h
@@ -27,11 +27,13 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _AlgPolicy, class _Iter, class _Sent, class _Type, class _Proj, class _Comp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
-__lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) {
- auto __len = _IterOps<_AlgPolicy>::distance(__first, __last);
-
+template <class _AlgPolicy, class _Iter, class _Type, class _Proj, class _Comp>
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter __lower_bound_bisecting(
+ _Iter __first,
+ const _Type& __value,
+ typename iterator_traits<_Iter>::difference_type __len,
+ _Comp& __comp,
+ _Proj& __proj) {
while (__len != 0) {
auto __l2 = std::__half_positive(__len);
_Iter __m = __first;
@@ -46,6 +48,48 @@ __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp,
return __first;
}
+// One-sided binary search, aka meta binary search, has been in the public domain for decades, and has the general
+// advantage of being \Omega(1) rather than the classic algorithm's \Omega(log(n)), with the downside of executing at
+// most 2*log(n) comparisons vs the classic algorithm's exact log(n). There are two scenarios in which it really shines:
+// the first one is when operating over non-random-access iterators, because the classic algorithm requires knowing the
+// container's size upfront, which adds \Omega(n) iterator increments to the complexity. The second one is when you're
+// traversing the container in order, trying to fast-forward to the next value: in that case, the classic algorithm
+// would yield \Omega(n*log(n)) comparisons and, for non-random-access iterators, \Omega(n^2) iterator increments,
+// whereas the one-sided version will yield O(n) operations on both counts, with a \Omega(log(n)) bound on the number of
+// comparisons.
+template <class _AlgPolicy, class _ForwardIterator, class _Sent, class _Type, class _Proj, class _Comp>
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
+__lower_bound_onesided(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) {
+ // step = 0, ensuring we can always short-circuit when distance is 1 later on
+ if (__first == __last || !std::__invoke(__comp, std::__invoke(__proj, *__first), __value))
+ return __first;
+
+ using _Distance = typename iterator_traits<_ForwardIterator>::difference_type;
+ for (_Distance __step = 1; __first != __last; __step <<= 1) {
+ auto __it = __first;
+ auto __dist = __step - _IterOps<_AlgPolicy>::__advance_to(__it, __step, __last);
+ // once we reach the last range where needle can be we must start
+ // looking inwards, bisecting that range
+ if (__it == __last || !std::__invoke(__comp, std::__invoke(__proj, *__it), __value)) {
+ // we've already checked the previous value and it was less, we can save
+ // one comparison by skipping bisection
+ if (__dist == 1)
+ return __it;
+ return std::__lower_bound_bisecting<_AlgPolicy>(__first, __value, __dist, __comp, __proj);
+ }
+ // range not found, move forward!
+ __first = __it;
+ }
+ return __first;
+}
+
+template <class _AlgPolicy, class _ForwardIterator, class _Sent, class _Type, class _Proj, class _Comp>
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
+__lower_bound(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) {
+ const auto __dist = _IterOps<_AlgPolicy>::distance(__first, __last);
+ return std::__lower_bound_bisecting<_AlgPolicy>(__first, __value, __dist, __comp, __proj);
+}
+
template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
diff --git a/libcxx/include/__algorithm/set_intersection.h b/libcxx/include/__algorithm/set_intersection.h
index 73d888d..bb0d86c 100644
--- a/libcxx/include/__algorithm/set_intersection.h
+++ b/libcxx/include/__algorithm/set_intersection.h
@@ -12,10 +12,15 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/iterator_operations.h>
+#include <__algorithm/lower_bound.h>
#include <__config>
+#include <__functional/identity.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
+#include <__type_traits/is_same.h>
+#include <__utility/exchange.h>
#include <__utility/move.h>
+#include <__utility/swap.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -38,10 +43,103 @@ struct __set_intersection_result {
: __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {}
};
-template <class _AlgPolicy, class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_intersection_result<_InIter1, _InIter2, _OutIter>
+// Helper for __set_intersection() with one-sided binary search: populate result and advance input iterators if they
+// are found to potentially contain the same value in two consecutive calls. This function is very intimately related to
+// the way it is used and doesn't attempt to abstract that, it's not appropriate for general usage outside of its
+// context.
+template <class _InForwardIter1, class _InForwardIter2, class _OutIter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_intersection_add_output_if_equal(
+ bool __may_be_equal,
+ _InForwardIter1& __first1,
+ _InForwardIter2& __first2,
+ _OutIter& __result,
+ bool& __prev_may_be_equal) {
+ if (__may_be_equal && __prev_may_be_equal) {
+ *__result = *__first1;
+ ++__result;
+ ++__first1;
+ ++__first2;
+ __prev_may_be_equal = false;
+ } else {
+ __prev_may_be_equal = __may_be_equal;
+ }
+}
+
+// With forward iterators we can make multiple passes over the data, allowing the use of one-sided binary search to
+// reduce best-case complexity to log(N). Understanding how we can use binary search and still respect complexity
+// guarantees is _not_ straightforward: the guarantee is "at most 2*(N+M)-1 comparisons", and one-sided binary search
+// will necessarily overshoot depending on the position of the needle in the haystack -- for instance, if we're
+// searching for 3 in (1, 2, 3, 4), we'll check if 3<1, then 3<2, then 3<4, and, finally, 3<3, for a total of 4
+// comparisons, when linear search would have yielded 3. However, because we won't need to perform the intervening
+// reciprocal comparisons (ie 1<3, 2<3, 4<3), that extra comparison doesn't run afoul of the guarantee. Additionally,
+// this type of scenario can only happen for match distances of up to 5 elements, because 2*log2(8) is 6, and we'll
+// still be worse-off at position 5 of an 8-element set. From then onwards these scenarios can't happen. TL;DR: we'll be
+// 1 comparison worse-off compared to the classic linear-searching algorithm if matching position 3 of a set with 4
+// elements, or position 5 if the set has 7 or 8 elements, but we'll never exceed the complexity guarantees from the
+// standard.
+template <class _AlgPolicy,
+ class _Compare,
+ class _InForwardIter1,
+ class _Sent1,
+ class _InForwardIter2,
+ class _Sent2,
+ class _OutIter>
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 __set_intersection_result<_InForwardIter1, _InForwardIter2, _OutIter>
__set_intersection(
- _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) {
+ _InForwardIter1 __first1,
+ _Sent1 __last1,
+ _InForwardIter2 __first2,
+ _Sent2 __last2,
+ _OutIter __result,
+ _Compare&& __comp,
+ std::forward_iterator_tag,
+ std::forward_iterator_tag) {
+ _LIBCPP_CONSTEXPR std::__identity __proj;
+ bool __prev_may_be_equal = false;
+
+ while (__first2 != __last2) {
+ _InForwardIter1 __first1_next =
+ std::__lower_bound_onesided<_AlgPolicy>(__first1, __last1, *__first2, __comp, __proj);
+ std::swap(__first1_next, __first1);
+ // keeping in mind that a==b iff !(a<b) && !(b<a):
+ // if we can't advance __first1, that means !(*__first1 < *_first2), therefore __may_be_equal==true
+ std::__set_intersection_add_output_if_equal(
+ __first1 == __first1_next, __first1, __first2, __result, __prev_may_be_equal);
+ if (__first1 == __last1)
+ break;
+
+ _InForwardIter2 __first2_next =
+ std::__lower_bound_onesided<_AlgPolicy>(__first2, __last2, *__first1, __comp, __proj);
+ std::swap(__first2_next, __first2);
+ std::__set_intersection_add_output_if_equal(
+ __first2 == __first2_next, __first1, __first2, __result, __prev_may_be_equal);
+ }
+ return __set_intersection_result<_InForwardIter1, _InForwardIter2, _OutIter>(
+ _IterOps<_AlgPolicy>::next(std::move(__first1), std::move(__last1)),
+ _IterOps<_AlgPolicy>::next(std::move(__first2), std::move(__last2)),
+ std::move(__result));
+}
+
+// input iterators are not suitable for multipass algorithms, so we stick to the classic single-pass version
+template <class _AlgPolicy,
+ class _Compare,
+ class _InInputIter1,
+ class _Sent1,
+ class _InInputIter2,
+ class _Sent2,
+ class _OutIter>
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 __set_intersection_result<_InInputIter1, _InInputIter2, _OutIter>
+__set_intersection(
+ _InInputIter1 __first1,
+ _Sent1 __last1,
+ _InInputIter2 __first2,
+ _Sent2 __last2,
+ _OutIter __result,
+ _Compare&& __comp,
+ std::input_iterator_tag,
+ std::input_iterator_tag) {
while (__first1 != __last1 && __first2 != __last2) {
if (__comp(*__first1, *__first2))
++__first1;
@@ -55,12 +153,28 @@ __set_intersection(
}
}
- return __set_intersection_result<_InIter1, _InIter2, _OutIter>(
+ return __set_intersection_result<_InInputIter1, _InInputIter2, _OutIter>(
_IterOps<_AlgPolicy>::next(std::move(__first1), std::move(__last1)),
_IterOps<_AlgPolicy>::next(std::move(__first2), std::move(__last2)),
std::move(__result));
}
+template <class _AlgPolicy, class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 __set_intersection_result<_InIter1, _InIter2, _OutIter>
+__set_intersection(
+ _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) {
+ return std::__set_intersection<_AlgPolicy>(
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__result),
+ std::forward<_Compare>(__comp),
+ typename std::_IterOps<_AlgPolicy>::template __iterator_category<_InIter1>(),
+ typename std::_IterOps<_AlgPolicy>::template __iterator_category<_InIter2>());
+}
+
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_intersection(
_InputIterator1 __first1,
diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
index ac564f0..c5fcc89 100644
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -41,7 +41,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
struct NAME<_Tp, __void_t<typename _Tp::PROPERTY > > : true_type {}
// __pointer
-_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_pointer, pointer);
template <class _Tp,
class _Alloc,
class _RawAlloc = __libcpp_remove_reference_t<_Alloc>,
diff --git a/libcxx/include/__memory/inout_ptr.h b/libcxx/include/__memory/inout_ptr.h
new file mode 100644
index 0000000..72e1a21
--- /dev/null
+++ b/libcxx/include/__memory/inout_ptr.h
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___INOUT_PTR_H
+#define _LIBCPP___INOUT_PTR_H
+
+#include <__config>
+#include <__memory/addressof.h>
+#include <__memory/pointer_traits.h>
+#include <__memory/shared_ptr.h>
+#include <__memory/unique_ptr.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/is_specialization.h>
+#include <__type_traits/is_void.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+#include <tuple>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+template <class _Smart, class _Pointer, class... _Args>
+class _LIBCPP_TEMPLATE_VIS inout_ptr_t {
+ static_assert(!__is_specialization_v<_Smart, shared_ptr>, "std::shared_ptr<> is not supported with std::inout_ptr.");
+
+public:
+ _LIBCPP_HIDE_FROM_ABI explicit inout_ptr_t(_Smart& __smart, _Args... __args)
+ : __s_(__smart), __a_(std::forward<_Args>(__args)...), __p_([&__smart] {
+ if constexpr (is_pointer_v<_Smart>) {
+ return __smart;
+ } else {
+ return __smart.get();
+ }
+ }()) {
+ if constexpr (requires { __s_.release(); }) {
+ __s_.release();
+ } else {
+ __s_ = _Smart();
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI inout_ptr_t(const inout_ptr_t&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI ~inout_ptr_t() {
+ // LWG-3897 inout_ptr will not update raw pointer to null
+ if constexpr (!is_pointer_v<_Smart>) {
+ if (!__p_) {
+ return;
+ }
+ }
+
+ using _SP = __pointer_of_or_t<_Smart, _Pointer>;
+ if constexpr (is_pointer_v<_Smart>) {
+ std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
+ std::move(__a_));
+ } else if constexpr (__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...>) {
+ std::apply([&](auto&&... __args) { __s_.reset(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
+ std::move(__a_));
+ } else {
+ static_assert(is_constructible_v<_Smart, _SP, _Args...>,
+ "The smart pointer must be constructible from arguments of types _Smart, _Pointer, _Args...");
+ std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
+ std::move(__a_));
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI operator _Pointer*() const noexcept { return std::addressof(const_cast<_Pointer&>(__p_)); }
+
+ _LIBCPP_HIDE_FROM_ABI operator void**() const noexcept
+ requires(!is_same_v<_Pointer, void*>)
+ {
+ static_assert(is_pointer_v<_Pointer>, "The conversion to void** requires _Pointer to be a raw pointer.");
+
+ return reinterpret_cast<void**>(static_cast<_Pointer*>(*this));
+ }
+
+private:
+ _Smart& __s_;
+ tuple<_Args...> __a_;
+ _Pointer __p_;
+};
+
+template <class _Pointer = void, class _Smart, class... _Args>
+_LIBCPP_HIDE_FROM_ABI auto inout_ptr(_Smart& __s, _Args&&... __args) {
+ using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>;
+ return std::inout_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...);
+}
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___INOUT_PTR_H
diff --git a/libcxx/include/__memory/out_ptr.h b/libcxx/include/__memory/out_ptr.h
new file mode 100644
index 0000000..95aa202
--- /dev/null
+++ b/libcxx/include/__memory/out_ptr.h
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___OUT_PTR_H
+#define _LIBCPP___OUT_PTR_H
+
+#include <__config>
+#include <__memory/addressof.h>
+#include <__memory/pointer_traits.h>
+#include <__memory/shared_ptr.h>
+#include <__memory/unique_ptr.h>
+#include <__type_traits/is_specialization.h>
+#include <__type_traits/is_void.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+#include <tuple>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+template <class _Smart, class _Pointer, class... _Args>
+class _LIBCPP_TEMPLATE_VIS out_ptr_t {
+ static_assert(!__is_specialization_v<_Smart, shared_ptr> || sizeof...(_Args) > 0,
+ "Using std::shared_ptr<> without a deleter in std::out_ptr is not supported.");
+
+public:
+ _LIBCPP_HIDE_FROM_ABI explicit out_ptr_t(_Smart& __smart, _Args... __args)
+ : __s_(__smart), __a_(std::forward<_Args>(__args)...), __p_() {
+ using _Ptr = decltype(__smart);
+ if constexpr (__resettable_smart_pointer<_Ptr>) {
+ __s_.reset();
+ } else if constexpr (is_constructible_v<_Smart>) {
+ __s_ = _Smart();
+ } else {
+ static_assert(__resettable_smart_pointer<_Ptr> || is_constructible_v<_Smart>,
+ "The adapted pointer type must have a reset() member function or be default constructible.");
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI out_ptr_t(const out_ptr_t&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI ~out_ptr_t() {
+ if (!__p_) {
+ return;
+ }
+
+ using _SP = __pointer_of_or_t<_Smart, _Pointer>;
+ if constexpr (__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...>) {
+ std::apply([&](auto&&... __args) { __s_.reset(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
+ std::move(__a_));
+ } else {
+ static_assert(is_constructible_v<_Smart, _SP, _Args...>,
+ "The smart pointer must be constructible from arguments of types _Smart, _Pointer, _Args...");
+ std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
+ std::move(__a_));
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI operator _Pointer*() const noexcept { return std::addressof(const_cast<_Pointer&>(__p_)); }
+
+ _LIBCPP_HIDE_FROM_ABI operator void**() const noexcept
+ requires(!is_same_v<_Pointer, void*>)
+ {
+ static_assert(is_pointer_v<_Pointer>, "The conversion to void** requires _Pointer to be a raw pointer.");
+
+ return reinterpret_cast<void**>(static_cast<_Pointer*>(*this));
+ }
+
+private:
+ _Smart& __s_;
+ tuple<_Args...> __a_;
+ _Pointer __p_ = _Pointer();
+};
+
+template <class _Pointer = void, class _Smart, class... _Args>
+_LIBCPP_HIDE_FROM_ABI auto out_ptr(_Smart& __s, _Args&&... __args) {
+ using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>;
+ return std::out_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...);
+}
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___OUT_PTR_H
diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h
index fcd2c3e..0914ace 100644
--- a/libcxx/include/__memory/pointer_traits.h
+++ b/libcxx/include/__memory/pointer_traits.h
@@ -20,19 +20,28 @@
#include <__type_traits/is_void.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
+#include <__utility/forward.h>
#include <cstddef>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Tp, class = void>
-struct __has_element_type : false_type {};
+// clang-format off
+#define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY) \
+ template <class _Tp, class = void> \
+ struct NAME : false_type {}; \
+ template <class _Tp> \
+ struct NAME<_Tp, __void_t<typename _Tp::PROPERTY> > : true_type {}
+// clang-format on
-template <class _Tp>
-struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {};
+_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer);
+_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type);
template <class _Ptr, bool = __has_element_type<_Ptr>::value>
struct __pointer_traits_element_type {};
@@ -240,6 +249,59 @@ to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) {
}
#endif
+#if _LIBCPP_STD_VER >= 23
+
+template <class _Tp>
+struct __pointer_of {};
+
+template <class _Tp>
+ requires(__has_pointer<_Tp>::value)
+struct __pointer_of<_Tp> {
+ using type = typename _Tp::pointer;
+};
+
+template <class _Tp>
+ requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value)
+struct __pointer_of<_Tp> {
+ using type = typename _Tp::element_type*;
+};
+
+template <class _Tp>
+ requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value &&
+ __has_element_type<pointer_traits<_Tp>>::value)
+struct __pointer_of<_Tp> {
+ using type = typename pointer_traits<_Tp>::element_type*;
+};
+
+template <typename _Tp>
+using __pointer_of_t = typename __pointer_of<_Tp>::type;
+
+template <class _Tp, class _Up>
+struct __pointer_of_or {
+ using type _LIBCPP_NODEBUG = _Up;
+};
+
+template <class _Tp, class _Up>
+ requires requires { typename __pointer_of_t<_Tp>; }
+struct __pointer_of_or<_Tp, _Up> {
+ using type _LIBCPP_NODEBUG = __pointer_of_t<_Tp>;
+};
+
+template <typename _Tp, typename _Up>
+using __pointer_of_or_t = typename __pointer_of_or<_Tp, _Up>::type;
+
+template <class _Smart>
+concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); };
+
+template <class _Smart, class _Pointer, class... _Args>
+concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p, _Args... __args) {
+ __s.reset(static_cast<__pointer_of_or_t<_Smart, _Pointer>>(__p), std::forward<_Args>(__args)...);
+};
+
+#endif
+
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___MEMORY_POINTER_TRAITS_H
diff --git a/libcxx/include/memory b/libcxx/include/memory
index d52ee7b..e1b8462 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -911,6 +911,22 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
template<size_t N, class T>
[[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20
+// [out.ptr.t], class template out_ptr_t
+template<class Smart, class Pointer, class... Args>
+ class out_ptr_t; // since c++23
+
+// [out.ptr], function template out_ptr
+template<class Pointer = void, class Smart, class... Args>
+ auto out_ptr(Smart& s, Args&&... args); // since c++23
+
+// [inout.ptr.t], class template inout_ptr_t
+template<class Smart, class Pointer, class... Args>
+ class inout_ptr_t; // since c++23
+
+// [inout.ptr], function template inout_ptr
+template<class Pointer = void, class Smart, class... Args>
+ auto inout_ptr(Smart& s, Args&&... args); // since c++23
+
} // std
*/
@@ -924,6 +940,8 @@ template<size_t N, class T>
#include <__memory/allocator_arg_t.h>
#include <__memory/allocator_traits.h>
#include <__memory/auto_ptr.h>
+#include <__memory/inout_ptr.h>
+#include <__memory/out_ptr.h>
#include <__memory/pointer_traits.h>
#include <__memory/raw_storage_iterator.h>
#include <__memory/shared_ptr.h>
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 5ed284d..43ab9c6 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1521,6 +1521,8 @@ module std_private_memory_concepts [system] {
module std_private_memory_construct_at [system] { header "__memory/construct_at.h" }
module std_private_memory_destruct_n [system] { header "__memory/destruct_n.h" }
module std_private_memory_fwd [system] { header "__fwd/memory.h" }
+module std_private_memory_inout_ptr [system] { header "__memory/inout_ptr.h" }
+module std_private_memory_out_ptr [system] { header "__memory/out_ptr.h" }
module std_private_memory_pointer_traits [system] { header "__memory/pointer_traits.h" }
module std_private_memory_ranges_construct_at [system] { header "__memory/ranges_construct_at.h" }
module std_private_memory_ranges_uninitialized_algorithms [system] {
diff --git a/libcxx/include/version b/libcxx/include/version
index 7d9fad1..68aa88a 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -477,7 +477,7 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_move_only_function 202110L
# undef __cpp_lib_optional
# define __cpp_lib_optional 202110L
-// # define __cpp_lib_out_ptr 202106L
+# define __cpp_lib_out_ptr 202106L
# define __cpp_lib_print 202207L
// # define __cpp_lib_ranges_as_const 202207L
# define __cpp_lib_ranges_as_rvalue 202207L
@@ -536,7 +536,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_mdspan 202406L
// # define __cpp_lib_optional_range_support 202406L
# undef __cpp_lib_out_ptr
-// # define __cpp_lib_out_ptr 202311L
+# define __cpp_lib_out_ptr 202311L
// # define __cpp_lib_philox_engine 202406L
// # define __cpp_lib_ranges_concat 202403L
# define __cpp_lib_ratio 202306L
diff --git a/libcxx/modules/std/memory.inc b/libcxx/modules/std/memory.inc
index 56c621c..c15f37a 100644
--- a/libcxx/modules/std/memory.inc
+++ b/libcxx/modules/std/memory.inc
@@ -177,17 +177,19 @@ export namespace std {
// [util.smartptr.atomic], atomic smart pointers
// using std::atomic;
+#if _LIBCPP_STD_VER >= 23
// [out.ptr.t], class template out_ptr_t
- // using std::out_ptr_t;
+ using std::out_ptr_t;
// [out.ptr], function template out_ptr
- // using std::out_ptr;
+ using std::out_ptr;
// [inout.ptr.t], class template inout_ptr_t
- // using std::inout_ptr_t;
+ using std::inout_ptr_t;
// [inout.ptr], function template inout_ptr
- // using std::inout_ptr;
+ using std::inout_ptr;
+#endif // _LIBCPP_STD_VER >= 23
#ifndef _LIBCPP_HAS_NO_THREADS
// [depr.util.smartptr.shared.atomic]
diff --git a/libcxx/test/configs/apple-libc++-shared.cfg.in b/libcxx/test/configs/apple-libc++-shared.cfg.in
new file mode 100644
index 0000000..5504bfd
--- /dev/null
+++ b/libcxx/test/configs/apple-libc++-shared.cfg.in
@@ -0,0 +1,51 @@
+# Testing configuration for Apple's system libc++.
+#
+# This configuration differs from a normal LLVM shared library configuration in
+# that we must use DYLD_LIBRARY_PATH to run the tests against the just-built library,
+# since Apple's libc++ has an absolute install_name.
+#
+# We also don't use a per-target include directory layout, so we have only one
+# include directory for the libc++ headers.
+#
+# Finally, we also link against an artificial shims library that provides
+# the functionality necessary for the upstream libc++ to be usable in place
+# of a system-provided libc++. Without that, attempting to replace the system
+# libc++ with DYLD_LIBRARY_PATH would result in missing symbols and other similar
+# issues since the upstream libc++ does not contain all the symbols provided by
+# the system library.
+
+lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
+
+import os, site
+site.addsitedir(os.path.join('@LIBCXX_SOURCE_DIR@', 'utils'))
+import libcxx.test.params, libcxx.test.config, libcxx.test.dsl
+ADDITIONAL_PARAMETERS = [
+ libcxx.test.dsl.Parameter(name='apple_system_shims', type=str,
+ actions=lambda path: [libcxx.test.dsl.AddSubstitution('%{apple-system-shims}', path)],
+ help="""
+ Path to a pre-built object file or static archive that contains shims necessary to
+ allow replacing the system libc++ by the just-built one.
+ """),
+]
+
+config.substitutions.append(('%{flags}',
+ '-isysroot {}'.format('@CMAKE_OSX_SYSROOT@') if '@CMAKE_OSX_SYSROOT@' else ''
+))
+config.substitutions.append(('%{compile_flags}',
+ '-nostdinc++ -I %{include-dir} -I %{libcxx-dir}/test/support'
+))
+config.substitutions.append(('%{link_flags}',
+ '-nostdlib++ -L %{lib-dir} -lc++ %{apple-system-shims}'
+))
+config.substitutions.append(('%{exec}',
+ '%{executor} --execdir %T --env DYLD_LIBRARY_PATH=%{lib-dir} -- '
+))
+
+config.stdlib = 'apple-libc++'
+
+libcxx.test.config.configure(
+ libcxx.test.params.DEFAULT_PARAMETERS + ADDITIONAL_PARAMETERS,
+ libcxx.test.features.DEFAULT_FEATURES,
+ config,
+ lit_config
+)
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/ranges_set_intersection.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/ranges_set_intersection.pass.cpp
index 5323bb1..f7870485 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/ranges_set_intersection.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/ranges_set_intersection.pass.cpp
@@ -28,6 +28,8 @@
#include <algorithm>
#include <array>
#include <concepts>
+#include <cstddef>
+#include <ranges>
#include "almost_satisfies_types.h"
#include "MoveOnly.h"
@@ -463,75 +465,6 @@ constexpr bool test() {
}
}
- // Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons and applications of each projection.
- {
- std::array<Data, 5> r1{{{1}, {3}, {5}, {7}, {9}}};
- std::array<Data, 5> r2{{{2}, {4}, {6}, {8}, {10}}};
- std::array<int, 0> expected{};
-
- const std::size_t maxOperation = 2 * (r1.size() + r2.size()) - 1;
-
- // iterator overload
- {
- std::array<Data, 0> out{};
- std::size_t numberOfComp = 0;
- std::size_t numberOfProj1 = 0;
- std::size_t numberOfProj2 = 0;
-
- const auto comp = [&numberOfComp](int x, int y) {
- ++numberOfComp;
- return x < y;
- };
-
- const auto proj1 = [&numberOfProj1](const Data& d) {
- ++numberOfProj1;
- return d.data;
- };
-
- const auto proj2 = [&numberOfProj2](const Data& d) {
- ++numberOfProj2;
- return d.data;
- };
-
- std::ranges::set_intersection(r1.begin(), r1.end(), r2.begin(), r2.end(), out.data(), comp, proj1, proj2);
-
- assert(std::ranges::equal(out, expected, {}, &Data::data));
- assert(numberOfComp < maxOperation);
- assert(numberOfProj1 < maxOperation);
- assert(numberOfProj2 < maxOperation);
- }
-
- // range overload
- {
- std::array<Data, 0> out{};
- std::size_t numberOfComp = 0;
- std::size_t numberOfProj1 = 0;
- std::size_t numberOfProj2 = 0;
-
- const auto comp = [&numberOfComp](int x, int y) {
- ++numberOfComp;
- return x < y;
- };
-
- const auto proj1 = [&numberOfProj1](const Data& d) {
- ++numberOfProj1;
- return d.data;
- };
-
- const auto proj2 = [&numberOfProj2](const Data& d) {
- ++numberOfProj2;
- return d.data;
- };
-
- std::ranges::set_intersection(r1, r2, out.data(), comp, proj1, proj2);
-
- assert(std::ranges::equal(out, expected, {}, &Data::data));
- assert(numberOfComp < maxOperation);
- assert(numberOfProj1 < maxOperation);
- assert(numberOfProj2 < maxOperation);
- }
- }
-
// Comparator convertible to bool
{
struct ConvertibleToBool {
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_complexity.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_complexity.pass.cpp
new file mode 100644
index 0000000..ddf4087
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_complexity.pass.cpp
@@ -0,0 +1,404 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <algorithm>
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// Algorithmic complexity tests for both std::set_intersection and std::ranges::set_intersection
+
+// template<InputIterator InIter1, InputIterator InIter2, typename OutIter>
+// requires OutputIterator<OutIter, InIter1::reference>
+// && OutputIterator<OutIter, InIter2::reference>
+// && HasLess<InIter2::value_type, InIter1::value_type>
+// && HasLess<InIter1::value_type, InIter2::value_type>
+// constexpr OutIter // constexpr after C++17
+// set_intersection(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
+// OutIter result);
+//
+// template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2,
+// weakly_incrementable O, class Comp = ranges::less,
+// class Proj1 = identity, class Proj2 = identity>
+// requires mergeable<I1, I2, O, Comp, Proj1, Proj2>
+// constexpr set_intersection_result<I1, I2, O>
+// set_intersection(I1 first1, S1 last1, I2 first2, S2 last2, O result,
+// Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20
+//
+// template<input_range R1, input_range R2, weakly_incrementable O,
+// class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity>
+// requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2>
+// constexpr set_intersection_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O>
+// set_intersection(R1&& r1, R2&& r2, O result,
+// Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <ranges>
+
+#include "test_iterators.h"
+
+namespace {
+
+// __debug_less will perform an additional comparison in an assertion
+static constexpr unsigned std_less_comparison_count_multiplier() noexcept {
+#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+ return 2;
+#else
+ return 1;
+#endif
+}
+
+struct [[nodiscard]] OperationCounts {
+ std::size_t comparisons{};
+ struct PerInput {
+ std::size_t proj{};
+ IteratorOpCounts iterops;
+
+ [[nodiscard]] constexpr bool isNotBetterThan(const PerInput& other) {
+ return proj >= other.proj && iterops.increments + iterops.decrements + iterops.zero_moves >=
+ other.iterops.increments + other.iterops.decrements + other.iterops.zero_moves;
+ }
+ };
+ std::array<PerInput, 2> in;
+
+ [[nodiscard]] constexpr bool isNotBetterThan(const OperationCounts& expect) {
+ return std_less_comparison_count_multiplier() * comparisons >= expect.comparisons &&
+ in[0].isNotBetterThan(expect.in[0]) && in[1].isNotBetterThan(expect.in[1]);
+ }
+};
+
+template <std::size_t ResultSize>
+struct counted_set_intersection_result {
+ std::array<int, ResultSize> result;
+ OperationCounts opcounts;
+
+ constexpr counted_set_intersection_result() = default;
+
+ constexpr explicit counted_set_intersection_result(std::array<int, ResultSize>&& contents) : result{contents} {}
+
+ constexpr void assertNotBetterThan(const counted_set_intersection_result& other) {
+ assert(result == other.result);
+ assert(opcounts.isNotBetterThan(other.opcounts));
+ }
+};
+
+template <std::size_t ResultSize>
+counted_set_intersection_result(std::array<int, ResultSize>) -> counted_set_intersection_result<ResultSize>;
+
+template <template <class...> class InIterType1,
+ template <class...>
+ class InIterType2,
+ class OutIterType,
+ std::size_t ResultSize,
+ std::ranges::input_range R1,
+ std::ranges::input_range R2>
+constexpr counted_set_intersection_result<ResultSize> counted_set_intersection(const R1& in1, const R2& in2) {
+ counted_set_intersection_result<ResultSize> out;
+
+ const auto comp = [&out](int x, int y) {
+ ++out.opcounts.comparisons;
+ return x < y;
+ };
+
+ operation_counting_iterator b1(InIterType1<decltype(in1.begin())>(in1.begin()), &out.opcounts.in[0].iterops);
+ operation_counting_iterator e1(InIterType1<decltype(in1.end()) >(in1.end()), &out.opcounts.in[0].iterops);
+
+ operation_counting_iterator b2(InIterType2<decltype(in2.begin())>(in2.begin()), &out.opcounts.in[1].iterops);
+ operation_counting_iterator e2(InIterType2<decltype(in2.end()) >(in2.end()), &out.opcounts.in[1].iterops);
+
+ std::set_intersection(b1, e1, b2, e2, OutIterType(out.result.data()), comp);
+
+ return out;
+}
+
+template <template <class...> class InIterType1,
+ template <class...>
+ class InIterType2,
+ class OutIterType,
+ std::size_t ResultSize,
+ std::ranges::input_range R1,
+ std::ranges::input_range R2>
+constexpr counted_set_intersection_result<ResultSize> counted_ranges_set_intersection(const R1& in1, const R2& in2) {
+ counted_set_intersection_result<ResultSize> out;
+
+ const auto comp = [&out](int x, int y) {
+ ++out.opcounts.comparisons;
+ return x < y;
+ };
+
+ const auto proj1 = [&out](const int& i) {
+ ++out.opcounts.in[0].proj;
+ return i;
+ };
+
+ const auto proj2 = [&out](const int& i) {
+ ++out.opcounts.in[1].proj;
+ return i;
+ };
+
+ operation_counting_iterator b1(InIterType1<decltype(in1.begin())>(in1.begin()), &out.opcounts.in[0].iterops);
+ operation_counting_iterator e1(InIterType1<decltype(in1.end()) >(in1.end()), &out.opcounts.in[0].iterops);
+
+ operation_counting_iterator b2(InIterType2<decltype(in2.begin())>(in2.begin()), &out.opcounts.in[1].iterops);
+ operation_counting_iterator e2(InIterType2<decltype(in2.end()) >(in2.end()), &out.opcounts.in[1].iterops);
+
+ std::ranges::subrange r1{b1, sentinel_wrapper<decltype(e1)>{e1}};
+ std::ranges::subrange r2{b2, sentinel_wrapper<decltype(e2)>{e2}};
+ std::same_as<std::ranges::set_intersection_result<decltype(e1), decltype(e2), OutIterType>> decltype(auto) result =
+ std::ranges::set_intersection(r1, r2, OutIterType{out.result.data()}, comp, proj1, proj2);
+ assert(base(result.in1) == base(e1));
+ assert(base(result.in2) == base(e2));
+ assert(base(result.out) == out.result.data() + out.result.size());
+
+ return out;
+}
+
+template <template <typename...> class In1, template <typename...> class In2, class Out>
+constexpr void testComplexityParameterizedIter() {
+ // Worst-case complexity:
+ // Let N=(last1 - first1) and M=(last2 - first2)
+ // At most 2*(N+M) - 1 comparisons and applications of each projection.
+ // At most 2*(N+M) iterator mutations.
+ {
+ std::array r1{1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
+ std::array r2{2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
+
+ counted_set_intersection_result<0> expected;
+ expected.opcounts.comparisons = 37;
+ expected.opcounts.in[0].proj = 37;
+ expected.opcounts.in[0].iterops.increments = 30;
+ expected.opcounts.in[0].iterops.decrements = 0;
+ expected.opcounts.in[1] = expected.opcounts.in[0];
+
+ expected.assertNotBetterThan(counted_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ expected.assertNotBetterThan(counted_ranges_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ }
+
+ {
+ std::array r1{1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
+ std::array r2{1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
+
+ counted_set_intersection_result expected(std::array{1, 3, 5, 7, 9, 11, 13, 15, 17, 19});
+ expected.opcounts.comparisons = 38;
+ expected.opcounts.in[0].proj = 38;
+ expected.opcounts.in[0].iterops.increments = 30;
+ expected.opcounts.in[0].iterops.decrements = 0;
+ expected.opcounts.in[1] = expected.opcounts.in[0];
+
+ expected.assertNotBetterThan(counted_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ expected.assertNotBetterThan(counted_ranges_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ }
+
+ // Lower complexity when there is low overlap between ranges: we can make 2*log(X) comparisons when one range
+ // has X elements that can be skipped over (and then 1 more to confirm that the value we found is equal).
+ {
+ std::array r1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ std::array r2{15};
+
+ counted_set_intersection_result expected(std::array{15});
+ expected.opcounts.comparisons = 9;
+ expected.opcounts.in[0].proj = 9;
+ expected.opcounts.in[0].iterops.increments = 23;
+ expected.opcounts.in[0].iterops.decrements = 0;
+ expected.opcounts.in[1].proj = 9;
+ expected.opcounts.in[1].iterops.increments = 1;
+ expected.opcounts.in[1].iterops.decrements = 0;
+
+ expected.assertNotBetterThan(counted_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ expected.assertNotBetterThan(counted_ranges_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ }
+
+ {
+ std::array r1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ std::array r2{0, 16};
+ counted_set_intersection_result<0> expected;
+
+ expected.opcounts.comparisons = 10;
+ expected.opcounts.in[0].proj = 10;
+ expected.opcounts.in[0].iterops.increments = 24;
+ expected.opcounts.in[0].iterops.decrements = 0;
+ expected.opcounts.in[1].proj = 10;
+ expected.opcounts.in[1].iterops.increments = 4;
+ expected.opcounts.in[1].iterops.decrements = 0;
+
+ expected.assertNotBetterThan(counted_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ expected.assertNotBetterThan(counted_ranges_set_intersection<In1, In2, Out, expected.result.size()>(r1, r2));
+ }
+}
+
+template <template <typename...> class In2, class Out>
+constexpr void testComplexityParameterizedIterPermutateIn1() {
+ //common_input_iterator
+ testComplexityParameterizedIter<forward_iterator, In2, Out>();
+ testComplexityParameterizedIter<bidirectional_iterator, In2, Out>();
+ testComplexityParameterizedIter<random_access_iterator, In2, Out>();
+}
+
+template <class Out>
+constexpr void testComplexityParameterizedIterPermutateIn1In2() {
+ testComplexityParameterizedIterPermutateIn1<forward_iterator, Out>();
+ testComplexityParameterizedIterPermutateIn1<bidirectional_iterator, Out>();
+ testComplexityParameterizedIterPermutateIn1<random_access_iterator, Out>();
+}
+
+constexpr bool testComplexity() {
+ testComplexityParameterizedIterPermutateIn1In2<forward_iterator<int*>>();
+ testComplexityParameterizedIterPermutateIn1In2<bidirectional_iterator<int*>>();
+ testComplexityParameterizedIterPermutateIn1In2<random_access_iterator<int*>>();
+ return true;
+}
+
+template <template <typename...> class In1, template <typename...> class In2, class Out>
+constexpr void testComplexityGuaranteesParameterizedIter() {
+ // now a more generic validation of the complexity guarantees when searching for a single value
+ for (unsigned range_size = 1; range_size < 20; ++range_size) {
+ std::ranges::iota_view<int, int> r1(0, range_size);
+ for (int i : r1) {
+ // At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons
+ counted_set_intersection_result<1> expected(std::array{i});
+ expected.opcounts.comparisons = 2 * (r1.size() + 1) - 1;
+ expected.opcounts.in[0].proj = expected.opcounts.comparisons;
+ expected.opcounts.in[1].proj = expected.opcounts.comparisons;
+ expected.opcounts.in[0].iterops.increments = 2 * r1.size();
+ expected.opcounts.in[1].iterops.increments = 2;
+ expected.opcounts.in[0].iterops.decrements = expected.opcounts.in[0].iterops.increments;
+ expected.opcounts.in[1].iterops.decrements = expected.opcounts.in[1].iterops.increments;
+
+ expected.assertNotBetterThan(
+ counted_set_intersection<In1, In2, Out, expected.result.size()>(r1, expected.result));
+ expected.assertNotBetterThan(
+ counted_ranges_set_intersection<In1, In2, Out, expected.result.size()>(r1, expected.result));
+ }
+ }
+}
+
+template <template <typename...> class In2, class Out>
+constexpr void testComplexityGuaranteesParameterizedIterPermutateIn1() {
+ //common_input_iterator
+ testComplexityGuaranteesParameterizedIter<forward_iterator, In2, Out>();
+ testComplexityGuaranteesParameterizedIter<bidirectional_iterator, In2, Out>();
+ testComplexityGuaranteesParameterizedIter<random_access_iterator, In2, Out>();
+}
+
+template <class Out>
+constexpr void testComplexityGuaranteesParameterizedIterPermutateIn1In2() {
+ testComplexityGuaranteesParameterizedIterPermutateIn1<forward_iterator, Out>();
+ testComplexityGuaranteesParameterizedIterPermutateIn1<bidirectional_iterator, Out>();
+ testComplexityGuaranteesParameterizedIterPermutateIn1<random_access_iterator, Out>();
+}
+
+constexpr bool testComplexityGuarantees() {
+ testComplexityGuaranteesParameterizedIterPermutateIn1In2<forward_iterator<int*>>();
+ testComplexityGuaranteesParameterizedIterPermutateIn1In2<bidirectional_iterator<int*>>();
+ testComplexityGuaranteesParameterizedIterPermutateIn1In2<random_access_iterator<int*>>();
+ return true;
+}
+
+constexpr bool testComplexityBasic() {
+ // Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons and applications of each projection.
+ std::array<int, 5> r1{1, 3, 5, 7, 9};
+ std::array<int, 5> r2{2, 4, 6, 8, 10};
+ std::array<int, 0> expected{};
+
+ const std::size_t maxOperation = std_less_comparison_count_multiplier() * (2 * (r1.size() + r2.size()) - 1);
+
+ // std::set_intersection
+ {
+ std::array<int, 0> out{};
+ std::size_t numberOfComp = 0;
+
+ const auto comp = [&numberOfComp](int x, int y) {
+ ++numberOfComp;
+ return x < y;
+ };
+
+ std::set_intersection(r1.begin(), r1.end(), r2.begin(), r2.end(), out.data(), comp);
+
+ assert(std::ranges::equal(out, expected));
+ assert(numberOfComp <= maxOperation);
+ }
+
+ // ranges::set_intersection iterator overload
+ {
+ std::array<int, 0> out{};
+ std::size_t numberOfComp = 0;
+ std::size_t numberOfProj1 = 0;
+ std::size_t numberOfProj2 = 0;
+
+ const auto comp = [&numberOfComp](int x, int y) {
+ ++numberOfComp;
+ return x < y;
+ };
+
+ const auto proj1 = [&numberOfProj1](int d) {
+ ++numberOfProj1;
+ return d;
+ };
+
+ const auto proj2 = [&numberOfProj2](int d) {
+ ++numberOfProj2;
+ return d;
+ };
+
+ std::ranges::set_intersection(r1.begin(), r1.end(), r2.begin(), r2.end(), out.data(), comp, proj1, proj2);
+
+ assert(std::ranges::equal(out, expected));
+ assert(numberOfComp <= maxOperation);
+ assert(numberOfProj1 <= maxOperation);
+ assert(numberOfProj2 <= maxOperation);
+ }
+
+ // ranges::set_intersection range overload
+ {
+ std::array<int, 0> out{};
+ std::size_t numberOfComp = 0;
+ std::size_t numberOfProj1 = 0;
+ std::size_t numberOfProj2 = 0;
+
+ const auto comp = [&numberOfComp](int x, int y) {
+ ++numberOfComp;
+ return x < y;
+ };
+
+ const auto proj1 = [&numberOfProj1](int d) {
+ ++numberOfProj1;
+ return d;
+ };
+
+ const auto proj2 = [&numberOfProj2](int d) {
+ ++numberOfProj2;
+ return d;
+ };
+
+ std::ranges::set_intersection(r1, r2, out.data(), comp, proj1, proj2);
+
+ assert(std::ranges::equal(out, expected));
+ assert(numberOfComp < maxOperation);
+ assert(numberOfProj1 < maxOperation);
+ assert(numberOfProj2 < maxOperation);
+ }
+ return true;
+}
+
+} // unnamed namespace
+
+int main(int, char**) {
+ testComplexityBasic();
+ testComplexity();
+ testComplexityGuarantees();
+
+ static_assert(testComplexityBasic());
+ static_assert(testComplexity());
+
+ // we hit maximum constexpr evaluation step limit even if we split this into
+ // the 3 types of the first type layer, so let's skip the constexpr validation
+ // static_assert(testComplexityGuarantees());
+
+ return 0;
+}
diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp
index cda49ac..18f8d15 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count.pass.cpp
@@ -12,6 +12,7 @@
#include <iterator>
+#include <algorithm>
#include <cassert>
#include "test_iterators.h"
@@ -32,12 +33,16 @@ constexpr void check(int* first, std::iter_difference_t<It> n, int* expected) {
// Count operations
if constexpr (Count) {
- auto it = stride_counting_iterator(It(first));
+ IteratorOpCounts ops;
+ auto it = operation_counting_iterator(It(first), &ops);
std::ranges::advance(it, n);
if constexpr (std::random_access_iterator<It>) {
- assert(it.stride_count() <= 1);
+ assert(ops.increments + ops.decrements <= 1);
} else {
- assert(it.stride_count() == abs(M));
+ const auto big = std::max(ops.increments, ops.decrements);
+ const auto small = std::min(ops.increments, ops.decrements);
+ assert(big == std::size_t(abs(M)));
+ assert(small == 0);
}
}
}
diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp
index 76439ef..d613105 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_count_sentinel.pass.cpp
@@ -38,14 +38,16 @@ check_forward(int* first, int* last, std::iter_difference_t<It> n, int* expected
// Count operations
if constexpr (Count) {
- auto it = stride_counting_iterator(It(first));
- auto sent = sentinel_wrapper(stride_counting_iterator(It(last)));
+ IteratorOpCounts ops;
+ auto it = operation_counting_iterator(It(first), &ops);
+ auto sent = sentinel_wrapper(operation_counting_iterator(It(last), &ops));
(void)std::ranges::advance(it, n, sent);
// We don't have a sized sentinel, so we have to increment one-by-one
// regardless of the iterator category.
- assert(it.stride_count() == M);
- assert(it.stride_displacement() == M);
- assert(it.equals_count() == expected_equals_count);
+ assert(static_cast<Difference>(ops.increments) == M);
+ assert(static_cast<Difference>(ops.decrements) == 0);
+ assert(ops.zero_moves == 0);
+ assert(ops.equal_cmps == static_cast<std::size_t>(expected_equals_count));
}
}
@@ -65,28 +67,24 @@ constexpr void check_forward_sized_sentinel(int* first, int* last, std::iter_dif
// Count operations
{
- auto it = stride_counting_iterator(It(first));
+ IteratorOpCounts ops;
+ auto it = operation_counting_iterator(It(first), &ops);
auto sent = distance_apriori_sentinel(size);
(void)std::ranges::advance(it, n, sent);
if constexpr (std::random_access_iterator<It>) {
- assert(it.stride_count() <= 1);
- assert(it.stride_displacement() <= 1);
+ assert(ops.increments + ops.zero_moves == 1);
+ assert(ops.decrements == 0);
} else {
- assert(it.stride_count() == M);
- assert(it.stride_displacement() == M);
+ assert(static_cast<Difference>(ops.increments) == M);
+ assert(ops.decrements == 0);
+ assert(ops.zero_moves == 0);
}
}
}
-struct Expected {
- int stride_count;
- int stride_displacement;
- int equals_count;
-};
-
template <bool Count, typename It>
constexpr void
-check_backward(int* first, int* last, std::iter_difference_t<It> n, int* expected, Expected expected_counts) {
+check_backward(int* first, int* last, std::iter_difference_t<It> n, int* expected, IteratorOpCounts expected_counts) {
// Check preconditions for `advance` when called with negative `n`
// (see [range.iter.op.advance]). In addition, allow `n == 0`.
assert(n <= 0);
@@ -105,16 +103,18 @@ check_backward(int* first, int* last, std::iter_difference_t<It> n, int* expecte
// Count operations
{
- auto it = stride_counting_iterator(It(last));
- auto sent = stride_counting_iterator(It(first));
- static_assert(std::bidirectional_iterator<stride_counting_iterator<It>>);
+ IteratorOpCounts ops;
+ auto it = operation_counting_iterator(It(last), &ops);
+ auto sent = operation_counting_iterator(It(first), &ops);
+ static_assert(std::bidirectional_iterator<operation_counting_iterator<It>>);
static_assert(Count == !std::sized_sentinel_for<It, It>);
(void)std::ranges::advance(it, n, sent);
- assert(it.stride_count() == expected_counts.stride_count);
- assert(it.stride_displacement() == expected_counts.stride_displacement);
- assert(it.equals_count() == expected_counts.equals_count);
+ assert(ops.increments == expected_counts.increments);
+ assert(ops.decrements == expected_counts.decrements);
+ assert(ops.zero_moves == expected_counts.zero_moves);
+ assert(ops.equal_cmps == expected_counts.equal_cmps);
}
}
@@ -217,21 +217,22 @@ constexpr bool test() {
{
int* expected = n > size ? range : range + size - n;
{
- Expected expected_counts = {
- .stride_count = static_cast<int>(range + size - expected),
- .stride_displacement = -expected_counts.stride_count,
- .equals_count = n > size ? size + 1 : n,
+ IteratorOpCounts expected_counts = {
+ .increments = 0,
+ .decrements = static_cast<std::size_t>(range + size - expected),
+ .equal_cmps = static_cast<std::size_t>(n > size ? size + 1 : n),
};
check_backward<true, bidirectional_iterator<int*>>(range, range + size, -n, expected, expected_counts);
}
{
- Expected expected_counts = {
+ IteratorOpCounts expected_counts = {
// If `n >= size`, the algorithm can just do `it = std::move(sent);`
// instead of doing iterator arithmetic.
- .stride_count = (n >= size) ? 0 : 1,
- .stride_displacement = (n >= size) ? 0 : 1,
- .equals_count = 0,
+ .increments = 0,
+ .decrements = static_cast<std::size_t>((n == 0 || n >= size) ? 0 : 1),
+ .zero_moves = static_cast<std::size_t>(n == 0 && size != 0 ? 1 : 0),
+ .equal_cmps = 0,
};
check_backward<false, random_access_iterator<int*>>(range, range + size, -n, expected, expected_counts);
diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
index 2e9a28e..147c26e 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp
@@ -12,6 +12,7 @@
#include <iterator>
+#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -31,11 +32,12 @@ constexpr void check_assignable(int* first, int* last, int* expected) {
// Count operations
if constexpr (Count) {
- auto it = stride_counting_iterator(It(first));
- auto sent = assignable_sentinel(stride_counting_iterator(It(last)));
+ IteratorOpCounts ops;
+ auto it = operation_counting_iterator(It(first), &ops);
+ auto sent = assignable_sentinel(operation_counting_iterator(It(last), &ops));
std::ranges::advance(it, sent);
assert(base(base(it)) == expected);
- assert(it.stride_count() == 0); // because we got here by assigning from last, not by incrementing
+ assert(ops.increments + ops.decrements == 0); // because we got here by assigning from last, not by incrementing
}
}
@@ -53,13 +55,17 @@ constexpr void check_sized_sentinel(int* first, int* last, int* expected) {
// Count operations
if constexpr (Count) {
- auto it = stride_counting_iterator(It(first));
+ IteratorOpCounts ops;
+ auto it = operation_counting_iterator(It(first), &ops);
auto sent = distance_apriori_sentinel(size);
std::ranges::advance(it, sent);
if constexpr (std::random_access_iterator<It>) {
- assert(it.stride_count() == 1);
+ assert(ops.increments + ops.decrements + ops.zero_moves == 1);
} else {
- assert(it.stride_count() == size);
+ const auto big = std::max(ops.increments, ops.decrements);
+ const auto small = std::min(ops.increments, ops.decrements);
+ assert(big == static_cast<size_t>(size > 0 ? size : -size));
+ assert(small == 0);
}
}
}
@@ -78,10 +84,14 @@ constexpr void check_sentinel(int* first, int* last, int* expected) {
// Count operations
if constexpr (Count) {
- auto it = stride_counting_iterator(It(first));
- auto sent = sentinel_wrapper(stride_counting_iterator(It(last)));
+ IteratorOpCounts ops;
+ auto it = operation_counting_iterator(It(first), &ops);
+ auto sent = sentinel_wrapper(operation_counting_iterator(It(last), &ops));
std::ranges::advance(it, sent);
- assert(it.stride_count() == size);
+ const auto big = std::max(ops.increments, ops.decrements);
+ const auto small = std::min(ops.increments, ops.decrements);
+ assert(big == static_cast<size_t>(size > 0 ? size : -size));
+ assert(small == 0);
}
}
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
index 45d9271..aa11706 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
@@ -485,17 +485,11 @@
# error "__cpp_lib_make_unique should have the value 201304L in c++23"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should be defined in c++23"
-# endif
-# if __cpp_lib_out_ptr != 202106L
-# error "__cpp_lib_out_ptr should have the value 202106L in c++23"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_out_ptr
+# error "__cpp_lib_out_ptr should be defined in c++23"
+# endif
+# if __cpp_lib_out_ptr != 202106L
+# error "__cpp_lib_out_ptr should have the value 202106L in c++23"
# endif
# ifndef __cpp_lib_ranges
@@ -622,17 +616,11 @@
# error "__cpp_lib_make_unique should have the value 201304L in c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should be defined in c++26"
-# endif
-# if __cpp_lib_out_ptr != 202311L
-# error "__cpp_lib_out_ptr should have the value 202311L in c++26"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_out_ptr
+# error "__cpp_lib_out_ptr should be defined in c++26"
+# endif
+# if __cpp_lib_out_ptr != 202311L
+# error "__cpp_lib_out_ptr should have the value 202311L in c++26"
# endif
# ifndef __cpp_lib_ranges
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index e1af306..945de95 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -5542,17 +5542,11 @@
# error "__cpp_lib_optional_range_support should not be defined before c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should be defined in c++23"
-# endif
-# if __cpp_lib_out_ptr != 202106L
-# error "__cpp_lib_out_ptr should have the value 202106L in c++23"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_out_ptr
+# error "__cpp_lib_out_ptr should be defined in c++23"
+# endif
+# if __cpp_lib_out_ptr != 202106L
+# error "__cpp_lib_out_ptr should have the value 202106L in c++23"
# endif
# if !defined(_LIBCPP_VERSION)
@@ -7383,17 +7377,11 @@
# endif
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should be defined in c++26"
-# endif
-# if __cpp_lib_out_ptr != 202311L
-# error "__cpp_lib_out_ptr should have the value 202311L in c++26"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_out_ptr
-# error "__cpp_lib_out_ptr should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_out_ptr
+# error "__cpp_lib_out_ptr should be defined in c++26"
+# endif
+# if __cpp_lib_out_ptr != 202311L
+# error "__cpp_lib_out_ptr should have the value 202311L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
index 28ac53c..7e01b58 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp
@@ -73,12 +73,12 @@ constexpr bool test() {
std::ranges::drop_view dropView7(MoveOnlyView(), 10);
assert(dropView7.begin() == globalBuff + 8);
- CountedView view8;
+ IteratorOpCounts opcounts;
+ CountedView view8(&opcounts);
+ ;
std::ranges::drop_view dropView8(view8, 5);
assert(base(base(dropView8.begin())) == globalBuff + 5);
- assert(dropView8.begin().stride_count() == 5);
- assert(base(base(dropView8.begin())) == globalBuff + 5);
- assert(dropView8.begin().stride_count() == 5);
+ assert(opcounts.increments == 5);
static_assert(!BeginInvocable<const ForwardView>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/types.h b/libcxx/test/std/ranges/range.adaptors/range.drop/types.h
index ae861bc..73d1e50 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.drop/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.drop/types.h
@@ -120,10 +120,14 @@ struct Range {
int *end() const;
};
-using CountedIter = stride_counting_iterator<forward_iterator<int*>>;
+using CountedIter = operation_counting_iterator<forward_iterator<int*>>;
struct CountedView : std::ranges::view_base {
- constexpr CountedIter begin() const { return CountedIter(ForwardIter(globalBuff)); }
- constexpr CountedIter end() const { return CountedIter(ForwardIter(globalBuff + 8)); }
+ explicit constexpr CountedView(IteratorOpCounts* opcounts) noexcept : opcounts_(opcounts) {}
+ constexpr CountedIter begin() const { return CountedIter(ForwardIter(globalBuff), opcounts_); }
+ constexpr CountedIter end() const { return CountedIter(ForwardIter(globalBuff + 8), opcounts_); }
+
+private:
+ IteratorOpCounts* opcounts_;
};
struct View : std::ranges::view_base {
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h
index 14f8572..cc5679f 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h
@@ -119,12 +119,6 @@ struct Range {
int *end() const;
};
-using CountedIter = stride_counting_iterator<forward_iterator<int*>>;
-struct CountedView : std::ranges::view_base {
- constexpr CountedIter begin() const { return CountedIter(ForwardIter(globalBuff)); }
- constexpr CountedIter end() const { return CountedIter(ForwardIter(globalBuff + 8)); }
-};
-
struct TimesTwo {
constexpr int operator()(int x) const { return x * 2; }
};
diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.general.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.general.pass.cpp
new file mode 100644
index 0000000..d55a0c2
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.general.pass.cpp
@@ -0,0 +1,206 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [inout.ptr], function template inout_ptr
+// template<class Pointer = void, class Smart, class... Args>
+// auto inout_ptr(Smart& s, Args&&... args); // since c++23
+
+#include <cassert>
+#include <memory>
+#include <utility>
+
+#include "../types.h"
+
+// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type.
+// The API returns a new valid object.
+void test_replace_int_p() {
+ auto replace_int_p = [](int** pp) {
+ assert(**pp == 90);
+
+ delete *pp;
+ *pp = new int{84};
+ };
+
+ // raw pointer
+ {
+ auto rPtr = new int{90};
+
+ replace_int_p(std::inout_ptr<int*>(rPtr));
+ assert(*rPtr == 84);
+
+ delete rPtr;
+ }
+
+ // std::unique_ptr
+ {
+ auto uPtr = std::make_unique<int>(90);
+
+ replace_int_p(std::inout_ptr(uPtr));
+ assert(*uPtr == 84);
+ }
+
+ {
+ MoveOnlyDeleter<int> del;
+ std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr{new int{90}};
+
+ replace_int_p(std::inout_ptr(uPtr, std::move(del)));
+ assert(*uPtr == 84);
+ assert(uPtr.get_deleter().wasMoveInitilized == true);
+ }
+
+ // pointer-like ConstructiblePtr
+ {
+ ConstructiblePtr<int> cPtr(new int{90});
+
+ replace_int_p(std::inout_ptr(cPtr));
+ assert(cPtr == 84);
+ }
+
+ // pointer-like ResettablePtr
+ {
+ ResettablePtr<int> rPtr(new int{90});
+
+ replace_int_p(std::inout_ptr(rPtr));
+ assert(rPtr == 84);
+ }
+
+ // pointer-like NonConstructiblePtr
+ {
+ NonConstructiblePtr<int> nPtr;
+ nPtr.reset(new int{90});
+
+ replace_int_p(std::inout_ptr(nPtr));
+ assert(nPtr == 84);
+ }
+}
+
+// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type.
+// The API returns `nullptr`.
+void test_replace_int_p_with_nullptr() {
+ auto replace_int_p_with_nullptr = [](int** pp) -> void {
+ assert(**pp == 90);
+
+ delete *pp;
+ *pp = nullptr;
+ };
+
+ // raw pointer
+ {
+ // LWG-3897 inout_ptr will not update raw pointer to null
+ auto rPtr = new int{90};
+
+ replace_int_p_with_nullptr(std::inout_ptr<int*>(rPtr));
+ assert(rPtr == nullptr);
+ }
+
+ // std::unique_ptr
+ {
+ auto uPtr = std::make_unique<int>(90);
+
+ replace_int_p_with_nullptr(std::inout_ptr(uPtr));
+ assert(uPtr == nullptr);
+ }
+}
+
+// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a void pointer type.
+// The API returns a new valid object.
+void test_replace_int_void_p() {
+ auto replace_int_void_p = [](void** pp) {
+ assert(*(static_cast<int*>(*pp)) == 90);
+
+ delete static_cast<int*>(*pp);
+ *pp = new int{84};
+ };
+
+ // raw pointer
+ {
+ auto rPtr = new int{90};
+
+ replace_int_void_p(std::inout_ptr<int*>(rPtr));
+ assert(*rPtr == 84);
+
+ delete rPtr;
+ }
+
+ // std::unique_ptr
+ {
+ auto uPtr = std::make_unique<int>(90);
+
+ replace_int_void_p(std::inout_ptr(uPtr));
+ assert(*uPtr == 84);
+ }
+}
+
+// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type.
+// The API returns `nullptr`.
+void test_replace_int_void_p_with_nullptr() {
+ auto replace_int_void_p_with_nullptr = [](void** pp) {
+ assert(*(static_cast<int*>(*pp)) == 90);
+
+ delete static_cast<int*>(*pp);
+ *pp = nullptr;
+ };
+
+ // raw pointer
+ {
+ auto rPtr = new int{90};
+
+ replace_int_void_p_with_nullptr(std::inout_ptr<int*>(rPtr));
+ assert(rPtr == nullptr);
+ }
+
+ // std::unique_ptr
+ {
+ auto uPtr = std::make_unique<int>(90);
+
+ replace_int_void_p_with_nullptr(std::inout_ptr(uPtr));
+ assert(uPtr == nullptr);
+ }
+}
+
+// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a void pointer type.
+// The API returns a new valid object.
+void test_replace_nullptr_with_int_p() {
+ auto replace_nullptr_with_int_p = [](int** pp) {
+ assert(*pp == nullptr);
+
+ *pp = new int{84};
+ };
+
+ // raw pointer
+ {
+ int* rPtr = nullptr;
+
+ replace_nullptr_with_int_p(std::inout_ptr<int*>(rPtr));
+ assert(*rPtr == 84);
+
+ delete rPtr;
+ }
+
+ // std::unique_ptr
+ {
+ std::unique_ptr<int> uPtr;
+
+ replace_nullptr_with_int_p(std::inout_ptr(uPtr));
+ assert(*uPtr == 84);
+ }
+}
+
+int main(int, char**) {
+ test_replace_int_p();
+ test_replace_int_p_with_nullptr();
+ test_replace_int_void_p();
+ test_replace_int_void_p_with_nullptr();
+ test_replace_nullptr_with_int_p();
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp
new file mode 100644
index 0000000..d6d7078
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [inout.ptr], function template inout_ptr
+// template<class Pointer = void, class Smart, class... Args>
+// auto inout_ptr(Smart& s, Args&&... args); // since c++23
+
+#include <memory>
+#include <tuple>
+
+#include "../types.h"
+
+int main(int, char**) {
+ // `std::inout_ptr<>` does not support `std::shared_ptr<>`.
+ {
+ std::shared_ptr<int> sPtr;
+
+ // expected-error-re@*:* {{static assertion failed due to requirement {{.*}}std::shared_ptr<> is not supported}}
+ std::ignore = std::inout_ptr(sPtr);
+ // expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::inout_ptr_t<shared_ptr<int>, _Ptr>' (aka 'inout_ptr_t<std::shared_ptr<int>, int *>'}}
+ std::ignore = std::inout_ptr<int*>(sPtr);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.convert.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.convert.pass.cpp
new file mode 100644
index 0000000..230402a
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.convert.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [inout.ptr.t], class template inout_ptr_t
+// template<class Smart, class Pointer, class... Args>
+// class inout_ptr_t; // since c++23
+
+// operator Pointer*() const noexcept;
+// operator void**() const noexcept;
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+
+int main(int, char**) {
+ // operator Pointer*()
+ {
+ std::unique_ptr<int> uPtr = std::make_unique<int>(84);
+
+ const std::inout_ptr_t<std::unique_ptr<int>, int*> ioPtr{uPtr};
+
+ static_assert(noexcept(ioPtr.operator int**()));
+ std::same_as<int**> decltype(auto) pPtr = ioPtr.operator int**();
+
+ assert(**pPtr == 84);
+ }
+
+ {
+ std::unique_ptr<int, std::default_delete<int>> uPtr = std::make_unique<int>(84);
+
+ const std::inout_ptr_t<decltype(uPtr), int*, std::default_delete<int>> ioPtr{uPtr, std::default_delete<int>{}};
+
+ static_assert(noexcept(ioPtr.operator int**()));
+ std::same_as<int**> decltype(auto) pPtr = ioPtr.operator int**();
+
+ assert(**pPtr == 84);
+ }
+
+ // operator void**()
+ {
+ std::unique_ptr<int> uPtr = std::make_unique<int>(84);
+
+ const std::inout_ptr_t<std::unique_ptr<int>, void*> ioPtr{uPtr};
+
+ static_assert(noexcept(ioPtr.operator void**()));
+ std::same_as<void**> decltype(auto) pPtr = ioPtr.operator void**();
+
+ assert(**reinterpret_cast<int**>(pPtr) == 84);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.ctor.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.ctor.pass.cpp
new file mode 100644
index 0000000..c7e173a
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.ctor.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [inout.ptr.t], class template inout_ptr_t
+// template<class Smart, class Pointer, class... Args>
+// class inout_ptr_t; // since c++23
+
+// explicit inout_ptr_t(Smart&, Args...);
+
+#include <cassert>
+#include <memory>
+
+#include "test_convertible.h"
+#include "../types.h"
+
+int main(int, char**) {
+ {
+ std::unique_ptr<int> uPtr;
+
+ std::inout_ptr_t<std::unique_ptr<int>, int*>{uPtr};
+
+ static_assert(
+ !test_convertible<std::inout_ptr_t<std::unique_ptr<int>, int*>>(), "This constructor must be explicit");
+
+ // Test the state of the pointer after construction. Complete tests are available in inout_ptr.general.pass.cpp.
+ assert(uPtr == nullptr);
+ }
+
+ {
+ auto deleter = [](auto* p) { delete p; };
+ std::unique_ptr<int, decltype(deleter)> uPtr;
+
+ std::inout_ptr_t<std::unique_ptr<int, decltype(deleter)>, int*>{uPtr};
+
+ static_assert(!test_convertible<std::inout_ptr_t<std::unique_ptr<int, decltype(deleter)>, int*>>(),
+ "This constructor must be explicit");
+
+ // Test the state of the pointer after construction. Complete tests are available in inout_ptr.general.pass.cpp.
+ assert(uPtr == nullptr);
+ }
+
+ {
+ std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr;
+
+ std::inout_ptr_t<decltype(uPtr), int*, MoveOnlyDeleter<int>>{uPtr, MoveOnlyDeleter<int>{}};
+
+ // Test the state of the pointer after construction. Complete tests are available in inout_ptr.general.pass.cpp.
+ assert(uPtr == nullptr);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.verify.cpp
new file mode 100644
index 0000000..2270c4c
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr_t.verify.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [inout.ptr.t], class template inout_ptr_t
+// template<class Smart, class Pointer, class... Args>
+// class inout_ptr_t; // since c++23
+
+#include <memory>
+
+int main(int, char**) {
+ // `std::inout_ptr<>` does not support `std::shared_ptr<>`.
+ {
+ std::shared_ptr<int> sPtr;
+
+ // expected-error-re@*:* {{static assertion failed due to requirement {{.*}}std::shared_ptr<> is not supported with std::inout_ptr.}}
+ std::inout_ptr_t<std::shared_ptr<int>, int*>{sPtr};
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.general.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.general.pass.cpp
new file mode 100644
index 0000000..a78e22f
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.general.pass.cpp
@@ -0,0 +1,230 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [out.ptr], function template out_ptr
+// template<class Pointer = void, class Smart, class... Args>
+// auto out_ptr(Smart& s, Args&&... args); // since c++23
+
+#include <cassert>
+#include <memory>
+#include <utility>
+
+#include "../types.h"
+
+// Test updating an `out_ptr_t`-managed pointer for an API with a non-void pointer type.
+// The API returns a new valid object.
+void test_get_int_p() {
+ auto get_int_p = [](int** pp) { *pp = new int{84}; };
+
+ // raw pointer
+ {
+ int* rPtr;
+
+ get_int_p(std::out_ptr<int*>(rPtr));
+ assert(*rPtr == 84);
+
+ delete rPtr;
+ }
+
+ // std::unique_ptr
+ {
+ std::unique_ptr<int> uPtr;
+
+ get_int_p(std::out_ptr(uPtr));
+ assert(*uPtr == 84);
+ }
+
+ {
+ MoveOnlyDeleter<int> del;
+ std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr;
+
+ get_int_p(std::out_ptr(uPtr, std::move(del)));
+ assert(*uPtr == 84);
+ assert(uPtr.get_deleter().wasMoveInitilized == true);
+ }
+
+ // std::shared_ptr
+ {
+ std::shared_ptr<int> sPtr;
+
+ get_int_p(std::out_ptr(sPtr, [](auto* p) {
+ assert(*p == 84);
+
+ delete p;
+ }));
+ assert(*sPtr == 84);
+ }
+
+ // pointer-like ConstructiblePtr
+ {
+ ConstructiblePtr<int> cPtr;
+
+ get_int_p(std::out_ptr(cPtr));
+ assert(cPtr == 84);
+ }
+
+ // pointer-like ResettablePtr
+ {
+ ResettablePtr<int> rPtr{nullptr};
+
+ get_int_p(std::out_ptr(rPtr));
+ assert(rPtr == 84);
+ }
+
+ // NonConstructiblePtr
+ {
+ NonConstructiblePtr<int> nPtr;
+
+ get_int_p(std::out_ptr(nPtr));
+ assert(nPtr == 84);
+ }
+}
+
+// Test updating an `out_ptr_t`-managed pointer for an API with a non-void pointer type.
+// The API returns `nullptr`.
+void test_get_int_p_nullptr() {
+ auto get_int_p_nullptr = [](int** pp) { *pp = nullptr; };
+ // raw pointer
+ {
+ int* rPtr;
+
+ get_int_p_nullptr(std::out_ptr<int*>(rPtr));
+ assert(rPtr == nullptr);
+
+ delete rPtr;
+ }
+
+ // std::unique_ptr
+ {
+ std::unique_ptr<int> uPtr;
+
+ get_int_p_nullptr(std::out_ptr(uPtr));
+ assert(uPtr == nullptr);
+ }
+
+ // std::shared_ptr
+ {
+ std::shared_ptr<int> sPtr;
+
+ get_int_p_nullptr(std::out_ptr(sPtr, [](auto* p) {
+ assert(p == nullptr);
+
+ delete p;
+ }));
+ assert(sPtr == nullptr);
+ }
+}
+
+// Test updating an `out_ptr_t`-managed pointer for an API with a void pointer type.
+// The API returns a new valid object.
+void test_get_int_void_p() {
+ auto get_int_void_p = [](void** pp) { *(reinterpret_cast<int**>(pp)) = new int{84}; };
+
+ // raw pointer
+ {
+ int* rPtr;
+
+ get_int_void_p(std::out_ptr(rPtr));
+ assert(*rPtr == 84);
+
+ delete rPtr;
+ }
+
+ // std::unique_ptr
+ {
+ std::unique_ptr<int> uPtr;
+
+ get_int_void_p(std::out_ptr(uPtr));
+ assert(*uPtr == 84);
+ }
+
+ // std::shared_ptr
+ {
+ std::shared_ptr<int> sPtr;
+
+ get_int_void_p(std::out_ptr(sPtr, [](auto* p) {
+ assert(*p == 84);
+
+ delete p;
+ }));
+ assert(*sPtr == 84);
+ }
+
+ // pointer-like ConstructiblePtr
+ {
+ ConstructiblePtr<int> cPtr;
+
+ get_int_void_p(std::out_ptr(cPtr));
+ assert(cPtr == 84);
+ }
+
+ // pointer-like ResettablePtr
+ {
+ ResettablePtr<int> rPtr{nullptr};
+
+ get_int_void_p(std::out_ptr(rPtr));
+ assert(rPtr == 84);
+ }
+
+ // NonConstructiblePtr
+ {
+ NonConstructiblePtr<int> nPtr;
+
+ get_int_void_p(std::out_ptr(nPtr));
+ assert(nPtr == 84);
+ }
+}
+
+// Test updating an `out_ptr_t`-managed pointer for an API with a void pointer type.
+// The API returns `nullptr`.
+void test_get_int_void_p_nullptr() {
+ auto get_int_void_p_nullptr = [](void** pp) { *pp = nullptr; };
+
+ // raw pointer
+ {
+ int* rPtr;
+
+ get_int_void_p_nullptr(std::out_ptr<int*>(rPtr));
+ assert(rPtr == nullptr);
+
+ delete rPtr;
+ }
+
+ // std::unique_ptr
+ {
+ std::unique_ptr<int> uPtr;
+
+ get_int_void_p_nullptr(std::out_ptr(uPtr));
+ assert(uPtr == nullptr);
+ }
+
+ // std::shared_ptr
+ {
+ std::shared_ptr<int> sPtr;
+
+ get_int_void_p_nullptr(std::out_ptr(sPtr, [](auto* p) {
+ assert(p == nullptr);
+
+ delete p;
+ }));
+ assert(sPtr == nullptr);
+ }
+}
+
+int main(int, char**) {
+ test_get_int_p();
+ test_get_int_p_nullptr();
+ test_get_int_void_p();
+ test_get_int_void_p_nullptr();
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp
new file mode 100644
index 0000000..1fe78ec
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [out.ptr], function template out_ptr
+// template<class Pointer = void, class Smart, class... Args>
+// auto out_ptr(Smart& s, Args&&... args); // since c++23
+
+#include <memory>
+#include <tuple>
+
+#include "../types.h"
+
+int main(int, char**) {
+ // `std::out_ptr<>` requires `std::shared_ptr<>` with a deleter.
+ {
+ std::shared_ptr<int> sPtr;
+
+ // expected-error-re@*:* {{static assertion failed due to requirement {{.*}}Using std::shared_ptr<> without a deleter in std::out_ptr is not supported.}}
+ std::ignore = std::out_ptr(sPtr);
+ // expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::out_ptr_t<shared_ptr<int>, _Ptr>' (aka 'out_ptr_t<std::shared_ptr<int>, int *>')}}
+ std::ignore = std::out_ptr<int*>(sPtr);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.convert.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.convert.pass.cpp
new file mode 100644
index 0000000..828a5d0
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.convert.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [out.ptr.t], class template out_ptr_t
+// template<class Smart, class Pointer, class... Args>
+// class out_ptr_t; // since c++23
+
+// operator Pointer*() const noexcept;
+// operator void**() const noexcept;
+
+#include <cassert>
+#include <concepts>
+#include <memory>
+
+int main(int, char**) {
+ // operator Pointer*()
+ {
+ std::unique_ptr<int> uPtr;
+
+ const std::out_ptr_t<std::unique_ptr<int>, int*> oPtr{uPtr};
+
+ static_assert(noexcept(oPtr.operator int**()));
+ std::same_as<int**> decltype(auto) pPtr = oPtr.operator int**();
+
+ assert(*pPtr == nullptr);
+ }
+
+ {
+ std::unique_ptr<int, std::default_delete<int>> uPtr;
+
+ const std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>> oPtr{uPtr, std::default_delete<int>{}};
+
+ static_assert(noexcept(oPtr.operator int**()));
+ std::same_as<int**> decltype(auto) pPtr = oPtr.operator int**();
+
+ assert(*pPtr == nullptr);
+ }
+
+ // operator void**()
+ {
+ std::unique_ptr<int> uPtr;
+
+ const std::out_ptr_t<std::unique_ptr<int>, void*> oPtr{uPtr};
+
+ static_assert(noexcept(oPtr.operator void**()));
+ std::same_as<void**> decltype(auto) pPtr = oPtr.operator void**();
+
+ assert(*pPtr == nullptr);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.ctor.pass.cpp b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.ctor.pass.cpp
new file mode 100644
index 0000000..29e1258
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.ctor.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [out.ptr.t], class template out_ptr_t
+// template<class Smart, class Pointer, class... Args>
+// class out_ptr_t; // since c++23
+
+// explicit out_ptr_t(Smart&, Args...);
+
+#include <cassert>
+#include <memory>
+
+#include "test_convertible.h"
+#include "../types.h"
+
+int main(int, char**) {
+ {
+ std::unique_ptr<int> uPtr;
+
+ std::out_ptr_t<std::unique_ptr<int>, int*>{uPtr};
+
+ static_assert(!test_convertible<std::out_ptr_t<std::unique_ptr<int>, int*>>(), "This constructor must be explicit");
+
+ // Test the state of the pointer after construction. Complete tests are available in out_ptr.general.pass.cpp
+ assert(uPtr == nullptr);
+ }
+
+ {
+ std::unique_ptr<int, std::default_delete<int>> uPtr;
+
+ std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>>{uPtr, std::default_delete<int>{}};
+
+ static_assert(!test_convertible<std::out_ptr_t<decltype(uPtr), int*, std::default_delete<int>>>(),
+ "This constructor must be explicit");
+
+ // Test the state of the pointer after construction. Complete tests are available in out_ptr.general.pass.cpp
+ assert(uPtr == nullptr);
+ }
+
+ {
+ std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr;
+
+ std::out_ptr_t<decltype(uPtr), int*, MoveOnlyDeleter<int>>{uPtr, MoveOnlyDeleter<int>{}};
+
+ // Test the state of the pointer after construction. Complete tests are available in out_ptr.general.pass.cpp
+ assert(uPtr == nullptr);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.verify.cpp
new file mode 100644
index 0000000..cbe96e7
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr_t.verify.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// [out.ptr.t], class template out_ptr_t
+// template<class Smart, class Pointer, class... Args>
+// class out_ptr_t; // since c++23
+
+#include <memory>
+
+int main(int, char**) {
+ // `std::out_ptr_t<>` requires `std::shared_ptr<>` with a deleter.
+ {
+ std::shared_ptr<int> sPtr;
+
+ // expected-error-re@*:* {{static assertion failed due to requirement {{.*}}Using std::shared_ptr<> without a deleter in std::out_ptr is not supported.}}
+ std::out_ptr_t<std::shared_ptr<int>, int*>{sPtr};
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/smartptr/adapt/types.h b/libcxx/test/std/utilities/smartptr/adapt/types.h
new file mode 100644
index 0000000..0da6007
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/adapt/types.h
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_LIBCXX_UTILITIES_SMARTPTR_ADAPT_TYPES_H
+#define TEST_LIBCXX_UTILITIES_SMARTPTR_ADAPT_TYPES_H
+
+#include <type_traits>
+#include <memory>
+
+#include "test_macros.h"
+
+// Custom deleters.
+
+template <typename T>
+struct MoveOnlyDeleter {
+ MoveOnlyDeleter() = default;
+ MoveOnlyDeleter(const MoveOnlyDeleter&) = delete;
+ MoveOnlyDeleter& operator=(const MoveOnlyDeleter&) = delete;
+ MoveOnlyDeleter(MoveOnlyDeleter&&) : wasMoveInitilized{true} {}
+ MoveOnlyDeleter& operator=(MoveOnlyDeleter&&) = default;
+
+ void operator()(T* p) const { delete p; }
+
+ bool wasMoveInitilized = false;
+};
+
+// Custom pointer types.
+
+template <typename T>
+struct ConstructiblePtr {
+ using pointer = T*;
+ std::unique_ptr<T> ptr;
+
+ ConstructiblePtr() = default;
+ explicit ConstructiblePtr(T* p) : ptr{p} {}
+
+ auto operator==(T val) { return *ptr == val; }
+
+ auto* get() const { return ptr.get(); }
+
+ void release() { ptr.release(); }
+};
+
+LIBCPP_STATIC_ASSERT(std::is_same_v<std::__pointer_of_t< ConstructiblePtr<int>>, int* >);
+static_assert(std::is_constructible_v< ConstructiblePtr<int>, int* >);
+
+struct ResetArg {};
+
+template <typename T>
+struct ResettablePtr {
+ using element_type = T;
+ std::unique_ptr<T> ptr;
+
+ explicit ResettablePtr(T* p) : ptr{p} {}
+
+ auto operator*() const { return *ptr; }
+
+ auto operator==(T val) { return *ptr == val; }
+
+ void reset() { ptr.reset(); }
+ void reset(T* p, ResetArg) { ptr.reset(p); }
+
+ auto* get() const { return ptr.get(); }
+
+ void release() { ptr.release(); }
+};
+
+LIBCPP_STATIC_ASSERT(std::is_same_v<std::__pointer_of_t< ResettablePtr<int>>, int* >);
+static_assert(std::is_constructible_v< ResettablePtr<int>, int* >);
+
+template <typename T>
+struct NonConstructiblePtr : public ResettablePtr<T> {
+ NonConstructiblePtr() : NonConstructiblePtr::ResettablePtr(nullptr) {};
+
+ void reset(T* p) { ResettablePtr<T>::ptr.reset(p); }
+};
+
+LIBCPP_STATIC_ASSERT(std::is_same_v<std::__pointer_of_t< NonConstructiblePtr<int>>, int* >);
+static_assert(!std::is_constructible_v< NonConstructiblePtr<int>, int* >);
+
+#endif // TEST_LIBCXX_UTILITIES_SMARTPTR_ADAPT_TYPES_H
diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index bb3ba21..31564a3 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -725,17 +725,18 @@ struct common_input_iterator {
# endif // TEST_STD_VER >= 20
-// Iterator adaptor that counts the number of times the iterator has had a successor/predecessor
-// operation or an equality comparison operation called. Has three recorders:
-// * `stride_count`, which records the total number of calls to an op++, op--, op+=, or op-=.
-// * `stride_displacement`, which records the displacement of the calls. This means that both
-// op++/op+= will increase the displacement counter by 1, and op--/op-= will decrease the
-// displacement counter by 1.
-// * `equals_count`, which records the total number of calls to an op== or op!=. If compared
-// against a sentinel object, that sentinel object must call the `record_equality_comparison`
-// function so that the comparison is counted correctly.
+struct IteratorOpCounts {
+ std::size_t increments = 0; ///< Number of times the iterator moved forward (++it, it++, it+=positive, it-=negative).
+ std::size_t decrements = 0; ///< Number of times the iterator moved backward (--it, it--, it-=positive, it+=negative).
+ std::size_t zero_moves = 0; ///< Number of times a call was made to move the iterator by 0 positions (it+=0, it-=0).
+ std::size_t equal_cmps = 0; ///< Total number of calls to op== or op!=. If compared against a sentinel object, that
+ /// sentinel object must call the `record_equality_comparison` function so that the
+ /// comparison is counted correctly.
+};
+
+// Iterator adaptor that records its operation counts in a IteratorOpCounts
template <class It>
-class stride_counting_iterator {
+class operation_counting_iterator {
public:
using value_type = typename iter_value_or_void<It>::type;
using difference_type = std::iter_difference_t<It>;
@@ -747,147 +748,160 @@ public:
std::conditional_t<std::input_iterator<It>, std::input_iterator_tag,
/* else */ std::output_iterator_tag
>>>>>;
+ using iterator_category = iterator_concept;
- stride_counting_iterator() requires std::default_initializable<It> = default;
-
- constexpr explicit stride_counting_iterator(It const& it) : base_(base(it)) { }
+ operation_counting_iterator()
+ requires std::default_initializable<It>
+ = default;
- friend constexpr It base(stride_counting_iterator const& it) { return It(it.base_); }
+ constexpr explicit operation_counting_iterator(It const& it, IteratorOpCounts* counts = nullptr)
+ : base_(base(it)), counts_(counts) {}
- constexpr difference_type stride_count() const { return stride_count_; }
+ constexpr operation_counting_iterator(const operation_counting_iterator& o) { *this = o; }
+ constexpr operation_counting_iterator(operation_counting_iterator&& o) { *this = o; }
- constexpr difference_type stride_displacement() const { return stride_displacement_; }
+ constexpr operation_counting_iterator& operator=(const operation_counting_iterator& o) = default;
+ constexpr operation_counting_iterator& operator=(operation_counting_iterator&& o) { return *this = o; }
- constexpr difference_type equals_count() const { return equals_count_; }
+ friend constexpr It base(operation_counting_iterator const& it) { return It(it.base_); }
constexpr decltype(auto) operator*() const { return *It(base_); }
constexpr decltype(auto) operator[](difference_type n) const { return It(base_)[n]; }
- constexpr stride_counting_iterator& operator++() {
- It tmp(base_);
- base_ = base(++tmp);
- ++stride_count_;
- ++stride_displacement_;
- return *this;
+ constexpr operation_counting_iterator& operator++() {
+ It tmp(base_);
+ base_ = base(++tmp);
+ moved_by(1);
+ return *this;
}
constexpr void operator++(int) { ++*this; }
- constexpr stride_counting_iterator operator++(int)
- requires std::forward_iterator<It>
+ constexpr operation_counting_iterator operator++(int)
+ requires std::forward_iterator<It>
{
- auto temp = *this;
- ++*this;
- return temp;
+ auto temp = *this;
+ ++*this;
+ return temp;
}
- constexpr stride_counting_iterator& operator--()
- requires std::bidirectional_iterator<It>
+ constexpr operation_counting_iterator& operator--()
+ requires std::bidirectional_iterator<It>
{
- It tmp(base_);
- base_ = base(--tmp);
- ++stride_count_;
- --stride_displacement_;
- return *this;
+ It tmp(base_);
+ base_ = base(--tmp);
+ moved_by(-1);
+ return *this;
}
- constexpr stride_counting_iterator operator--(int)
- requires std::bidirectional_iterator<It>
+ constexpr operation_counting_iterator operator--(int)
+ requires std::bidirectional_iterator<It>
{
- auto temp = *this;
- --*this;
- return temp;
+ auto temp = *this;
+ --*this;
+ return temp;
}
- constexpr stride_counting_iterator& operator+=(difference_type const n)
- requires std::random_access_iterator<It>
+ constexpr operation_counting_iterator& operator+=(difference_type const n)
+ requires std::random_access_iterator<It>
{
- It tmp(base_);
- base_ = base(tmp += n);
- ++stride_count_;
- ++stride_displacement_;
- return *this;
+ It tmp(base_);
+ base_ = base(tmp += n);
+ moved_by(n);
+ return *this;
}
- constexpr stride_counting_iterator& operator-=(difference_type const n)
- requires std::random_access_iterator<It>
+ constexpr operation_counting_iterator& operator-=(difference_type const n)
+ requires std::random_access_iterator<It>
{
- It tmp(base_);
- base_ = base(tmp -= n);
- ++stride_count_;
- --stride_displacement_;
- return *this;
+ It tmp(base_);
+ base_ = base(tmp -= n);
+ moved_by(-n);
+ return *this;
}
- friend constexpr stride_counting_iterator operator+(stride_counting_iterator it, difference_type n)
- requires std::random_access_iterator<It>
+ friend constexpr operation_counting_iterator operator+(operation_counting_iterator it, difference_type n)
+ requires std::random_access_iterator<It>
{
- return it += n;
+ return it += n;
}
- friend constexpr stride_counting_iterator operator+(difference_type n, stride_counting_iterator it)
- requires std::random_access_iterator<It>
+ friend constexpr operation_counting_iterator operator+(difference_type n, operation_counting_iterator it)
+ requires std::random_access_iterator<It>
{
- return it += n;
+ return it += n;
}
- friend constexpr stride_counting_iterator operator-(stride_counting_iterator it, difference_type n)
- requires std::random_access_iterator<It>
+ friend constexpr operation_counting_iterator operator-(operation_counting_iterator it, difference_type n)
+ requires std::random_access_iterator<It>
{
- return it -= n;
+ return it -= n;
}
- friend constexpr difference_type operator-(stride_counting_iterator const& x, stride_counting_iterator const& y)
- requires std::sized_sentinel_for<It, It>
+ friend constexpr difference_type
+ operator-(operation_counting_iterator const& x, operation_counting_iterator const& y)
+ requires std::sized_sentinel_for<It, It>
{
- return base(x) - base(y);
+ return base(x) - base(y);
}
- constexpr void record_equality_comparison() const { ++equals_count_; }
+ constexpr void record_equality_comparison() const {
+ if (counts_ != nullptr)
+ ++counts_->equal_cmps;
+ }
- constexpr bool operator==(stride_counting_iterator const& other) const
- requires std::sentinel_for<It, It>
+ constexpr bool operator==(operation_counting_iterator const& other) const
+ requires std::sentinel_for<It, It>
{
record_equality_comparison();
return It(base_) == It(other.base_);
}
- friend constexpr bool operator<(stride_counting_iterator const& x, stride_counting_iterator const& y)
- requires std::random_access_iterator<It>
+ friend constexpr bool operator<(operation_counting_iterator const& x, operation_counting_iterator const& y)
+ requires std::random_access_iterator<It>
{
- return It(x.base_) < It(y.base_);
+ return It(x.base_) < It(y.base_);
}
- friend constexpr bool operator>(stride_counting_iterator const& x, stride_counting_iterator const& y)
- requires std::random_access_iterator<It>
+ friend constexpr bool operator>(operation_counting_iterator const& x, operation_counting_iterator const& y)
+ requires std::random_access_iterator<It>
{
- return It(x.base_) > It(y.base_);
+ return It(x.base_) > It(y.base_);
}
- friend constexpr bool operator<=(stride_counting_iterator const& x, stride_counting_iterator const& y)
- requires std::random_access_iterator<It>
+ friend constexpr bool operator<=(operation_counting_iterator const& x, operation_counting_iterator const& y)
+ requires std::random_access_iterator<It>
{
- return It(x.base_) <= It(y.base_);
+ return It(x.base_) <= It(y.base_);
}
- friend constexpr bool operator>=(stride_counting_iterator const& x, stride_counting_iterator const& y)
- requires std::random_access_iterator<It>
+ friend constexpr bool operator>=(operation_counting_iterator const& x, operation_counting_iterator const& y)
+ requires std::random_access_iterator<It>
{
- return It(x.base_) >= It(y.base_);
+ return It(x.base_) >= It(y.base_);
}
template <class T>
void operator,(T const &) = delete;
private:
+ constexpr void moved_by(difference_type n) {
+ if (counts_ == nullptr)
+ return;
+ if (n > 0)
+ ++counts_->increments;
+ else if (n < 0)
+ ++counts_->decrements;
+ else
+ ++counts_->zero_moves;
+ }
+
decltype(base(std::declval<It>())) base_;
- difference_type stride_count_ = 0;
- difference_type stride_displacement_ = 0;
- mutable difference_type equals_count_ = 0;
+ IteratorOpCounts* counts_ = nullptr;
};
template <class It>
-stride_counting_iterator(It) -> stride_counting_iterator<It>;
+operation_counting_iterator(It) -> operation_counting_iterator<It>;
#endif // TEST_STD_VER > 17
diff --git a/libcxx/utils/ci/apple-install-libcxx.sh b/libcxx/utils/ci/apple-install-libcxx.sh
index ddefabe..4872253 100755
--- a/libcxx/utils/ci/apple-install-libcxx.sh
+++ b/libcxx/utils/ci/apple-install-libcxx.sh
@@ -114,8 +114,14 @@ for arch in ${architectures}; do
# Then LLVM would guess the LLVM_DEFAULT_TARGET_TRIPLE properly and we wouldn't have to specify it.
target=$(xcrun clang -arch ${arch} -xc - -### 2>&1 | grep --only-matching -E '"-triple" ".+?"' | grep --only-matching -E '"[^ ]+-apple-[^ ]+?"' | tr -d '"')
- step "Building libc++.dylib and libc++abi.dylib for architecture ${arch}"
mkdir -p "${build_dir}/${arch}"
+
+ step "Building shims to make libc++ compatible with the system libc++ on Apple platforms when running the tests"
+ shims_library="${build_dir}/${arch}/apple-system-shims.a"
+ # Note that this doesn't need to match the Standard version used to build the rest of the library.
+ xcrun clang++ -c -std=c++2b -target ${target} "${llvm_root}/libcxxabi/src/vendor/apple/shims.cpp" -static -o "${shims_library}"
+
+ step "Building libc++.dylib and libc++abi.dylib for architecture ${arch}"
xcrun cmake -S "${llvm_root}/runtimes" \
-B "${build_dir}/${arch}" \
-GNinja \
@@ -127,9 +133,9 @@ for arch in ${architectures}; do
-DCMAKE_OSX_ARCHITECTURES="${arch}" \
-DLIBCXXABI_LIBRARY_VERSION="${version}" \
-DLIBCXX_LIBRARY_VERSION="${version}" \
- -DLIBCXX_TEST_PARAMS="target_triple=${target};stdlib=apple-libc++" \
- -DLIBCXXABI_TEST_PARAMS="target_triple=${target};stdlib=apple-libc++" \
- -DLIBUNWIND_TEST_PARAMS="target_triple=${target};stdlib=apple-libc++"
+ -DLIBCXX_TEST_PARAMS="target_triple=${target};apple_system_shims=${shims_library}" \
+ -DLIBCXXABI_TEST_PARAMS="target_triple=${target};apple_system_shims=${shims_library}" \
+ -DLIBUNWIND_TEST_PARAMS="target_triple=${target};apple_system_shims=${shims_library}"
if [ "$headers_only" = true ]; then
xcrun cmake --build "${build_dir}/${arch}" --target install-cxx-headers install-cxxabi-headers -- -v
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 65ba2f8..a09beb2 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -949,7 +949,6 @@ feature_test_macros = [
"c++26": 202311, # P2833R2 Freestanding Library: inout expected span
},
"headers": ["memory"],
- "unimplemented": True,
},
{
"name": "__cpp_lib_parallel_algorithm",
diff --git a/libcxxabi/src/vendor/apple/shims.cpp b/libcxxabi/src/vendor/apple/shims.cpp
new file mode 100644
index 0000000..65152f7
--- /dev/null
+++ b/libcxxabi/src/vendor/apple/shims.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+//
+// These shims implement symbols that are present in the system libc++ on Apple platforms
+// but are not implemented in upstream libc++. This allows testing libc++ under a system
+// library configuration, which requires the just-built libc++ to be ABI compatible with
+// the system library it is replacing.
+//
+
+#include <cstddef>
+#include <new>
+
+namespace std { // purposefully not versioned, like align_val_t
+enum class __type_descriptor_t : unsigned long long;
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, std::__type_descriptor_t) {
+ return ::operator new(__sz);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, const std::nothrow_t& __nt,
+ std::__type_descriptor_t) noexcept {
+ return ::operator new(__sz, __nt);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, std::__type_descriptor_t) {
+ return ::operator new[](__sz);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, const std::nothrow_t& __nt,
+ std::__type_descriptor_t) noexcept {
+ return ::operator new(__sz, __nt);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::__type_descriptor_t) noexcept {
+ return ::operator delete(__p);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, const std::nothrow_t& __nt,
+ std::__type_descriptor_t) noexcept {
+ return ::operator delete(__p, __nt);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::__type_descriptor_t) noexcept {
+ return ::operator delete[](__p);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, const std::nothrow_t& __nt,
+ std::__type_descriptor_t) noexcept {
+ return ::operator delete[](__p, __nt);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::size_t __sz, std::__type_descriptor_t) noexcept {
+ return ::operator delete(__p, __sz);
+}
+
+_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::size_t __sz, std::__type_descriptor_t) noexcept {
+ return ::operator delete[](__p, __sz);
+}
diff --git a/libcxxabi/test/configs/apple-libc++abi-shared.cfg.in b/libcxxabi/test/configs/apple-libc++abi-shared.cfg.in
new file mode 100644
index 0000000..537fe82
--- /dev/null
+++ b/libcxxabi/test/configs/apple-libc++abi-shared.cfg.in
@@ -0,0 +1,49 @@
+# Testing configuration for Apple's system libc++abi.
+#
+# This configuration differs from a normal LLVM shared library configuration in
+# that we must use DYLD_LIBRARY_PATH to run the tests against the just-built library,
+# since Apple's libc++abi has an absolute install_name.
+#
+# Finally, we also link against an artificial shims library that provides
+# the functionality necessary for the upstream libc++abi to be usable in place
+# of a system-provided libc++abi. Without that, attempting to replace the system
+# libc++abi with DYLD_LIBRARY_PATH would result in missing symbols and other similar
+# issues since the upstream libc++abi does not contain all the symbols provided by
+# the system library.
+
+lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
+
+import os, site
+site.addsitedir(os.path.join('@LIBCXXABI_LIBCXX_PATH@', 'utils'))
+import libcxx.test.params, libcxx.test.config, libcxx.test.dsl
+ADDITIONAL_PARAMETERS = [
+ libcxx.test.dsl.Parameter(name='apple_system_shims', type=str,
+ actions=lambda path: [libcxx.test.dsl.AddSubstitution('%{apple-system-shims}', path)],
+ help="""
+ Path to a pre-built object file or static archive that contains shims necessary to
+ allow replacing the system libc++abi by the just-built one.
+ """),
+]
+
+config.substitutions.append(('%{flags}',
+ '-isysroot {}'.format('@CMAKE_OSX_SYSROOT@') if '@CMAKE_OSX_SYSROOT@' else ''
+))
+config.substitutions.append(('%{compile_flags}',
+ '-nostdinc++ -I %{include} -I %{cxx-include} -I %{cxx-target-include} %{maybe-include-libunwind} -D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS ' +
+ '-I %{libcxx}/test/support -I %{libcxx}/src'
+))
+config.substitutions.append(('%{link_flags}',
+ '-nostdlib++ -L %{lib} -lc++ %{apple-system-shims}'
+))
+config.substitutions.append(('%{exec}',
+ '%{executor} --execdir %T --env DYLD_LIBRARY_PATH=%{lib} -- '
+))
+
+config.stdlib = 'apple-libc++'
+
+libcxx.test.config.configure(
+ libcxx.test.params.DEFAULT_PARAMETERS + ADDITIONAL_PARAMETERS,
+ libcxx.test.features.DEFAULT_FEATURES,
+ config,
+ lit_config
+)
diff --git a/lldb/bindings/headers.swig b/lldb/bindings/headers.swig
index c915046..c0dde90 100644
--- a/lldb/bindings/headers.swig
+++ b/lldb/bindings/headers.swig
@@ -21,6 +21,7 @@
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBCommunication.h"
#include "lldb/API/SBCompileUnit.h"
+#include "lldb/API/SBSaveCoreOptions.h"
#include "lldb/API/SBData.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBDeclaration.h"
diff --git a/lldb/bindings/interface/SBSaveCoreOptionsDocstrings.i b/lldb/bindings/interface/SBSaveCoreOptionsDocstrings.i
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lldb/bindings/interface/SBSaveCoreOptionsDocstrings.i
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index 0953f4c..8a6fed9 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -25,6 +25,7 @@
%include "./interface/SBCommandReturnObjectDocstrings.i"
%include "./interface/SBCommunicationDocstrings.i"
%include "./interface/SBCompileUnitDocstrings.i"
+%include "./interface/SBSaveCoreOptionsDocstrings.i"
%include "./interface/SBDataDocstrings.i"
%include "./interface/SBDebuggerDocstrings.i"
%include "./interface/SBDeclarationDocstrings.i"
@@ -101,6 +102,7 @@
%include "lldb/API/SBCommandReturnObject.h"
%include "lldb/API/SBCommunication.h"
%include "lldb/API/SBCompileUnit.h"
+%include "lldb/API/SBSaveCoreOptions.h"
%include "lldb/API/SBData.h"
%include "lldb/API/SBDebugger.h"
%include "lldb/API/SBDeclaration.h"
diff --git a/lldb/include/lldb/API/LLDB.h b/lldb/include/lldb/API/LLDB.h
index d8cc9f5..40368e0 100644
--- a/lldb/include/lldb/API/LLDB.h
+++ b/lldb/include/lldb/API/LLDB.h
@@ -57,6 +57,7 @@
#include "lldb/API/SBQueue.h"
#include "lldb/API/SBQueueItem.h"
#include "lldb/API/SBReproducer.h"
+#include "lldb/API/SBSaveCoreOptions.h"
#include "lldb/API/SBSection.h"
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBStatisticsOptions.h"
diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index 87c0a1c..f42e2be 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -61,6 +61,7 @@ class LLDB_API SBCommandPluginInterface;
class LLDB_API SBCommandReturnObject;
class LLDB_API SBCommunication;
class LLDB_API SBCompileUnit;
+class LLDB_API SBSaveCoreOptions;
class LLDB_API SBData;
class LLDB_API SBDebugger;
class LLDB_API SBDeclaration;
diff --git a/lldb/include/lldb/API/SBError.h b/lldb/include/lldb/API/SBError.h
index 1a720a4..17f2c6c 100644
--- a/lldb/include/lldb/API/SBError.h
+++ b/lldb/include/lldb/API/SBError.h
@@ -77,6 +77,7 @@ protected:
friend class SBBreakpointName;
friend class SBCommandReturnObject;
friend class SBCommunication;
+ friend class SBSaveCoreOptions;
friend class SBData;
friend class SBDebugger;
friend class SBFile;
diff --git a/lldb/include/lldb/API/SBFileSpec.h b/lldb/include/lldb/API/SBFileSpec.h
index beefa19..3664184 100644
--- a/lldb/include/lldb/API/SBFileSpec.h
+++ b/lldb/include/lldb/API/SBFileSpec.h
@@ -78,6 +78,7 @@ private:
friend class SBTarget;
friend class SBThread;
friend class SBTrace;
+ friend class SBSaveCoreOptions;
SBFileSpec(const lldb_private::FileSpec &fspec);
diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h
index a6ab7ae..778be79 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -378,6 +378,12 @@ public:
/// \param[in] file_name - The name of the file to save the core file to.
lldb::SBError SaveCore(const char *file_name);
+ /// Save the state of the process with the desired settings
+ /// as defined in the options object.
+ ///
+ /// \param[in] options - The options to use when saving the core file.
+ lldb::SBError SaveCore(SBSaveCoreOptions &options);
+
/// Query the address load_addr and store the details of the memory
/// region that contains it in the supplied SBMemoryRegionInfo object.
/// To iterate over all memory regions use GetMemoryRegionList.
diff --git a/lldb/include/lldb/API/SBSaveCoreOptions.h b/lldb/include/lldb/API/SBSaveCoreOptions.h
new file mode 100644
index 0000000..b8659bf1
--- /dev/null
+++ b/lldb/include/lldb/API/SBSaveCoreOptions.h
@@ -0,0 +1,69 @@
+//===-- SBSaveCoreOptions.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_API_SBSAVECOREOPTIONS_H
+#define LLDB_API_SBSAVECOREOPTIONS_H
+
+#include "lldb/API/SBDefines.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
+
+namespace lldb {
+
+class LLDB_API SBSaveCoreOptions {
+public:
+ SBSaveCoreOptions();
+ SBSaveCoreOptions(const lldb::SBSaveCoreOptions &rhs);
+ ~SBSaveCoreOptions() = default;
+
+ const SBSaveCoreOptions &operator=(const lldb::SBSaveCoreOptions &rhs);
+
+ /// Set the plugin name. Supplying null or empty string will reset
+ /// the option.
+ ///
+ /// \param plugin Name of the object file plugin.
+ SBError SetPluginName(const char *plugin);
+
+ /// Get the Core dump plugin name, if set.
+ ///
+ /// \return The name of the plugin, or null if not set.
+ const char *GetPluginName() const;
+
+ /// Set the Core dump style.
+ ///
+ /// \param style The style of the core dump.
+ void SetStyle(lldb::SaveCoreStyle style);
+
+ /// Get the Core dump style, if set.
+ ///
+ /// \return The core dump style, or undefined if not set.
+ lldb::SaveCoreStyle GetStyle() const;
+
+ /// Set the output file path
+ ///
+ /// \param output_file a
+ /// \class SBFileSpec object that describes the output file.
+ void SetOutputFile(SBFileSpec output_file);
+
+ /// Get the output file spec
+ ///
+ /// \return The output file spec.
+ SBFileSpec GetOutputFile() const;
+
+ /// Reset all options.
+ void Clear();
+
+protected:
+ friend class SBProcess;
+ lldb_private::SaveCoreOptions &ref() const;
+
+private:
+ std::unique_ptr<lldb_private::SaveCoreOptions> m_opaque_up;
+}; // SBSaveCoreOptions
+} // namespace lldb
+
+#endif // LLDB_API_SBSAVECOREOPTIONS_H
diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index f2296e2..38a291d 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -178,6 +178,8 @@ public:
static bool UnregisterPlugin(ObjectFileCreateInstance create_callback);
+ static bool IsRegisteredObjectFilePluginName(llvm::StringRef name);
+
static ObjectFileCreateInstance
GetObjectFileCreateCallbackAtIndex(uint32_t idx);
@@ -191,9 +193,7 @@ public:
GetObjectFileCreateMemoryCallbackForPluginName(llvm::StringRef name);
static Status SaveCore(const lldb::ProcessSP &process_sp,
- const FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
- llvm::StringRef plugin_name);
+ const lldb_private::SaveCoreOptions &core_options);
// ObjectContainer
static bool RegisterPlugin(
diff --git a/lldb/include/lldb/Symbol/SaveCoreOptions.h b/lldb/include/lldb/Symbol/SaveCoreOptions.h
new file mode 100644
index 0000000..583bc1f
--- /dev/null
+++ b/lldb/include/lldb/Symbol/SaveCoreOptions.h
@@ -0,0 +1,44 @@
+//===-- SaveCoreOptions.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_SaveCoreOPTIONS_H
+#define LLDB_SOURCE_PLUGINS_OBJECTFILE_SaveCoreOPTIONS_H
+
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+#include <optional>
+#include <string>
+
+namespace lldb_private {
+
+class SaveCoreOptions {
+public:
+ SaveCoreOptions(){};
+ ~SaveCoreOptions() = default;
+
+ lldb_private::Status SetPluginName(const char *name);
+ std::optional<std::string> GetPluginName() const;
+
+ void SetStyle(lldb::SaveCoreStyle style);
+ lldb::SaveCoreStyle GetStyle() const;
+
+ void SetOutputFile(lldb_private::FileSpec file);
+ const std::optional<lldb_private::FileSpec> GetOutputFile() const;
+
+ void Clear();
+
+private:
+ std::optional<std::string> m_plugin_name;
+ std::optional<lldb_private::FileSpec> m_file;
+ std::optional<lldb::SaveCoreStyle> m_style;
+};
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_SaveCoreOPTIONS_H
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index cdd9b51..10eaf1e 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -9,6 +9,7 @@
#ifndef LLDB_LLDB_PRIVATE_INTERFACES_H
#define LLDB_LLDB_PRIVATE_INTERFACES_H
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
@@ -55,8 +56,7 @@ typedef ObjectFile *(*ObjectFileCreateMemoryInstance)(
const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,
const lldb::ProcessSP &process_sp, lldb::addr_t offset);
typedef bool (*ObjectFileSaveCore)(const lldb::ProcessSP &process_sp,
- const FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
+ const lldb_private::SaveCoreOptions &options,
Status &error);
typedef EmulateInstruction *(*EmulateInstructionCreateInstance)(
const ArchSpec &arch, InstructionType inst_type);
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index 6397101..a32bc58 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -56,6 +56,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
SBCommandReturnObject.cpp
SBCommunication.cpp
SBCompileUnit.cpp
+ SBSaveCoreOptions.cpp
SBData.cpp
SBDebugger.cpp
SBDeclaration.cpp
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index efb3c8d..b88f897 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -40,6 +40,7 @@
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBMemoryRegionInfoList.h"
+#include "lldb/API/SBSaveCoreOptions.h"
#include "lldb/API/SBScriptObject.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
@@ -1216,13 +1217,28 @@ bool SBProcess::IsInstrumentationRuntimePresent(
lldb::SBError SBProcess::SaveCore(const char *file_name) {
LLDB_INSTRUMENT_VA(this, file_name);
- return SaveCore(file_name, "", SaveCoreStyle::eSaveCoreFull);
+ SBSaveCoreOptions options;
+ options.SetOutputFile(SBFileSpec(file_name));
+ options.SetStyle(SaveCoreStyle::eSaveCoreFull);
+ return SaveCore(options);
}
lldb::SBError SBProcess::SaveCore(const char *file_name,
const char *flavor,
SaveCoreStyle core_style) {
LLDB_INSTRUMENT_VA(this, file_name, flavor, core_style);
+ SBSaveCoreOptions options;
+ options.SetOutputFile(SBFileSpec(file_name));
+ options.SetStyle(core_style);
+ SBError error = options.SetPluginName(flavor);
+ if (error.Fail())
+ return error;
+ return SaveCore(options);
+}
+
+lldb::SBError SBProcess::SaveCore(SBSaveCoreOptions &options) {
+
+ LLDB_INSTRUMENT_VA(this, options);
lldb::SBError error;
ProcessSP process_sp(GetSP());
@@ -1239,10 +1255,7 @@ lldb::SBError SBProcess::SaveCore(const char *file_name,
return error;
}
- FileSpec core_file(file_name);
- FileSystem::Instance().Resolve(core_file);
- error.ref() = PluginManager::SaveCore(process_sp, core_file, core_style,
- flavor);
+ error.ref() = PluginManager::SaveCore(process_sp, options.ref());
return error;
}
diff --git a/lldb/source/API/SBSaveCoreOptions.cpp b/lldb/source/API/SBSaveCoreOptions.cpp
new file mode 100644
index 0000000..6c3f745
--- /dev/null
+++ b/lldb/source/API/SBSaveCoreOptions.cpp
@@ -0,0 +1,85 @@
+//===-- SBSaveCoreOptions.cpp -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBSaveCoreOptions.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
+#include "lldb/Utility/Instrumentation.h"
+
+#include "Utils.h"
+
+using namespace lldb;
+
+SBSaveCoreOptions::SBSaveCoreOptions() {
+ LLDB_INSTRUMENT_VA(this)
+
+ m_opaque_up = std::make_unique<lldb_private::SaveCoreOptions>();
+}
+
+SBSaveCoreOptions::SBSaveCoreOptions(const SBSaveCoreOptions &rhs) {
+ LLDB_INSTRUMENT_VA(this, rhs);
+
+ m_opaque_up = clone(rhs.m_opaque_up);
+}
+
+const SBSaveCoreOptions &
+SBSaveCoreOptions::operator=(const SBSaveCoreOptions &rhs) {
+ LLDB_INSTRUMENT_VA(this, rhs);
+
+ if (this != &rhs)
+ m_opaque_up = clone(rhs.m_opaque_up);
+ return *this;
+}
+
+SBError SBSaveCoreOptions::SetPluginName(const char *name) {
+ LLDB_INSTRUMENT_VA(this, name);
+ lldb_private::Status error = m_opaque_up->SetPluginName(name);
+ return SBError(error);
+}
+
+void SBSaveCoreOptions::SetStyle(lldb::SaveCoreStyle style) {
+ LLDB_INSTRUMENT_VA(this, style);
+ m_opaque_up->SetStyle(style);
+}
+
+void SBSaveCoreOptions::SetOutputFile(lldb::SBFileSpec file_spec) {
+ LLDB_INSTRUMENT_VA(this, file_spec);
+ m_opaque_up->SetOutputFile(file_spec.ref());
+}
+
+const char *SBSaveCoreOptions::GetPluginName() const {
+ LLDB_INSTRUMENT_VA(this);
+ const auto name = m_opaque_up->GetPluginName();
+ if (!name)
+ return nullptr;
+ return lldb_private::ConstString(name.value()).GetCString();
+}
+
+SBFileSpec SBSaveCoreOptions::GetOutputFile() const {
+ LLDB_INSTRUMENT_VA(this);
+ const auto file_spec = m_opaque_up->GetOutputFile();
+ if (file_spec)
+ return SBFileSpec(file_spec.value());
+ return SBFileSpec();
+}
+
+lldb::SaveCoreStyle SBSaveCoreOptions::GetStyle() const {
+ LLDB_INSTRUMENT_VA(this);
+ return m_opaque_up->GetStyle();
+}
+
+void SBSaveCoreOptions::Clear() {
+ LLDB_INSTRUMENT_VA(this);
+ m_opaque_up->Clear();
+}
+
+lldb_private::SaveCoreOptions &SBSaveCoreOptions::ref() const {
+ return *m_opaque_up.get();
+}
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 8685d5761..50695af 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -1273,13 +1273,13 @@ public:
switch (short_option) {
case 'p':
- m_requested_plugin_name = option_arg.str();
+ error = m_core_dump_options.SetPluginName(option_arg.data());
break;
case 's':
- m_requested_save_core_style =
+ m_core_dump_options.SetStyle(
(lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values,
- eSaveCoreUnspecified, error);
+ eSaveCoreUnspecified, error));
break;
default:
llvm_unreachable("Unimplemented option");
@@ -1289,13 +1289,11 @@ public:
}
void OptionParsingStarting(ExecutionContext *execution_context) override {
- m_requested_save_core_style = eSaveCoreUnspecified;
- m_requested_plugin_name.clear();
+ m_core_dump_options.Clear();
}
// Instance variables to hold the values for command options.
- SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified;
- std::string m_requested_plugin_name;
+ SaveCoreOptions m_core_dump_options;
};
protected:
@@ -1305,13 +1303,14 @@ protected:
if (command.GetArgumentCount() == 1) {
FileSpec output_file(command.GetArgumentAtIndex(0));
FileSystem::Instance().Resolve(output_file);
- SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
- Status error =
- PluginManager::SaveCore(process_sp, output_file, corefile_style,
- m_options.m_requested_plugin_name);
+ auto &core_dump_options = m_options.m_core_dump_options;
+ core_dump_options.SetOutputFile(output_file);
+ Status error = PluginManager::SaveCore(process_sp, core_dump_options);
if (error.Success()) {
- if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly ||
- corefile_style == SaveCoreStyle::eSaveCoreStackOnly) {
+ if (core_dump_options.GetStyle() ==
+ SaveCoreStyle::eSaveCoreDirtyOnly ||
+ core_dump_options.GetStyle() ==
+ SaveCoreStyle::eSaveCoreStackOnly) {
result.AppendMessageWithFormat(
"\nModified-memory or stack-memory only corefile "
"created. This corefile may \n"
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index b428370..759ef3a 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -12,6 +12,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
@@ -639,6 +640,18 @@ static ObjectFileInstances &GetObjectFileInstances() {
return g_instances;
}
+bool PluginManager::IsRegisteredObjectFilePluginName(llvm::StringRef name) {
+ if (name.empty())
+ return false;
+
+ const auto &instances = GetObjectFileInstances().GetInstances();
+ for (auto &instance : instances) {
+ if (instance.name == name)
+ return true;
+ }
+ return false;
+}
+
bool PluginManager::RegisterPlugin(
llvm::StringRef name, llvm::StringRef description,
ObjectFileCreateInstance create_callback,
@@ -689,12 +702,22 @@ PluginManager::GetObjectFileCreateMemoryCallbackForPluginName(
}
Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp,
- const FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
- llvm::StringRef plugin_name) {
- if (plugin_name.empty()) {
+ const lldb_private::SaveCoreOptions &options) {
+ Status error;
+ if (!options.GetOutputFile()) {
+ error.SetErrorString("No output file specified");
+ return error;
+ }
+
+ if (!process_sp) {
+ error.SetErrorString("Invalid process");
+ return error;
+ }
+
+ if (!options.GetPluginName().has_value()) {
// Try saving core directly from the process plugin first.
- llvm::Expected<bool> ret = process_sp->SaveCore(outfile.GetPath());
+ llvm::Expected<bool> ret =
+ process_sp->SaveCore(options.GetOutputFile()->GetPath());
if (!ret)
return Status(ret.takeError());
if (ret.get())
@@ -702,17 +725,20 @@ Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp,
}
// Fall back to object plugins.
- Status error;
+ const auto &plugin_name = options.GetPluginName().value_or("");
auto &instances = GetObjectFileInstances().GetInstances();
for (auto &instance : instances) {
if (plugin_name.empty() || instance.name == plugin_name) {
- if (instance.save_core &&
- instance.save_core(process_sp, outfile, core_style, error))
+ if (instance.save_core && instance.save_core(process_sp, options, error))
return error;
}
}
- error.SetErrorString(
- "no ObjectFile plugins were able to save a core for this process");
+
+ // Check to see if any of the object file plugins tried and failed to save.
+ // If none ran, set the error message.
+ if (error.Success())
+ error.SetErrorString(
+ "no ObjectFile plugins were able to save a core for this process");
return error;
}
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 0dcb1be..2c70054 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -6519,14 +6519,15 @@ struct page_object {
};
bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
- const FileSpec &outfile,
- lldb::SaveCoreStyle &core_style, Status &error) {
- if (!process_sp)
- return false;
-
- // Default on macOS is to create a dirty-memory-only corefile.
+ const lldb_private::SaveCoreOptions &options,
+ Status &error) {
+ auto core_style = options.GetStyle();
if (core_style == SaveCoreStyle::eSaveCoreUnspecified)
core_style = SaveCoreStyle::eSaveCoreDirtyOnly;
+ // The FileSpec and Process are already checked in PluginManager::SaveCore.
+ assert(options.GetOutputFile().has_value());
+ assert(process_sp);
+ const FileSpec outfile = options.GetOutputFile().value();
Target &target = process_sp->GetTarget();
const ArchSpec target_arch = target.GetArchitecture();
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 55bc688..e7af90e 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -62,8 +62,7 @@ public:
lldb_private::ModuleSpecList &specs);
static bool SaveCore(const lldb::ProcessSP &process_sp,
- const lldb_private::FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
+ const lldb_private::SaveCoreOptions &options,
lldb_private::Status &error);
static bool MagicBytesMatch(lldb::DataBufferSP data_sp, lldb::addr_t offset,
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp
index 7c875aa..faa144b 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp
+++ b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp
@@ -56,18 +56,20 @@ size_t ObjectFileMinidump::GetModuleSpecifications(
}
bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP &process_sp,
- const lldb_private::FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
+ const lldb_private::SaveCoreOptions &options,
lldb_private::Status &error) {
- // Set default core style if it isn't set.
+ // Output file and process_sp are both checked in PluginManager::SaveCore.
+ assert(options.GetOutputFile().has_value());
+ assert(process_sp);
+
+ // Minidump defaults to stacks only.
+ SaveCoreStyle core_style = options.GetStyle();
if (core_style == SaveCoreStyle::eSaveCoreUnspecified)
core_style = SaveCoreStyle::eSaveCoreStackOnly;
- if (!process_sp)
- return false;
-
llvm::Expected<lldb::FileUP> maybe_core_file = FileSystem::Instance().Open(
- outfile, File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate);
+ options.GetOutputFile().value(),
+ File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate);
if (!maybe_core_file) {
error = maybe_core_file.takeError();
return false;
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
index b5c4044..0cd31a0 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
+++ b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
@@ -55,8 +55,7 @@ public:
// Saves dump in Minidump file format
static bool SaveCore(const lldb::ProcessSP &process_sp,
- const lldb_private::FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
+ const lldb_private::SaveCoreOptions &options,
lldb_private::Status &error);
private:
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index be0020c..bda691a 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -355,11 +355,12 @@ size_t ObjectFilePECOFF::GetModuleSpecifications(
}
bool ObjectFilePECOFF::SaveCore(const lldb::ProcessSP &process_sp,
- const lldb_private::FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
+ const lldb_private::SaveCoreOptions &options,
lldb_private::Status &error) {
- core_style = eSaveCoreFull;
- return SaveMiniDump(process_sp, outfile, error);
+ // Outfile and process_sp are validated by PluginManager::SaveCore
+ assert(options.GetOutputFile().has_value());
+ assert(process_sp);
+ return SaveMiniDump(process_sp, options, error);
}
bool ObjectFilePECOFF::MagicBytesMatch(DataBufferSP data_sp) {
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index c59701f..2eb2b3b 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -82,8 +82,7 @@ public:
lldb_private::ModuleSpecList &specs);
static bool SaveCore(const lldb::ProcessSP &process_sp,
- const lldb_private::FileSpec &outfile,
- lldb::SaveCoreStyle &core_style,
+ const lldb_private::SaveCoreOptions &options,
lldb_private::Status &error);
static bool MagicBytesMatch(lldb::DataBufferSP data_sp);
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
index e5cb369..61cd74d 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
@@ -21,11 +21,12 @@
namespace lldb_private {
bool SaveMiniDump(const lldb::ProcessSP &process_sp,
- const lldb_private::FileSpec &outfile,
+ const SaveCoreOptions &core_options,
lldb_private::Status &error) {
if (!process_sp)
return false;
#ifdef _WIN32
+ const auto &outfile = core_options.GetOutputFile().value();
HANDLE process_handle = ::OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_sp->GetID());
const std::string file_name = outfile.GetPath();
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h b/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h
index 04b93e22..03c0ece 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h
@@ -14,7 +14,7 @@
namespace lldb_private {
bool SaveMiniDump(const lldb::ProcessSP &process_sp,
- const lldb_private::FileSpec &outfile,
+ const SaveCoreOptions &core_options,
lldb_private::Status &error);
} // namespace lldb_private
diff --git a/lldb/source/Symbol/CMakeLists.txt b/lldb/source/Symbol/CMakeLists.txt
index ad3488d..e49477d 100644
--- a/lldb/source/Symbol/CMakeLists.txt
+++ b/lldb/source/Symbol/CMakeLists.txt
@@ -6,6 +6,7 @@ add_lldb_library(lldbSymbol NO_PLUGIN_DEPENDENCIES
CompilerDecl.cpp
CompilerDeclContext.cpp
CompilerType.cpp
+ SaveCoreOptions.cpp
DWARFCallFrameInfo.cpp
DebugMacros.cpp
DeclVendor.cpp
diff --git a/lldb/source/Symbol/SaveCoreOptions.cpp b/lldb/source/Symbol/SaveCoreOptions.cpp
new file mode 100644
index 0000000..0f6fdac
--- /dev/null
+++ b/lldb/source/Symbol/SaveCoreOptions.cpp
@@ -0,0 +1,53 @@
+//===-- SaveCoreOptions.cpp -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/SaveCoreOptions.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Status SaveCoreOptions::SetPluginName(const char *name) {
+ Status error;
+ if (!name || !name[0]) {
+ m_plugin_name = std::nullopt;
+ return error;
+ }
+
+ if (!PluginManager::IsRegisteredObjectFilePluginName(name)) {
+ error.SetErrorStringWithFormat(
+ "plugin name '%s' is not a valid ObjectFile plugin name", name);
+ return error;
+ }
+
+ m_plugin_name = name;
+ return error;
+}
+
+void SaveCoreOptions::SetStyle(lldb::SaveCoreStyle style) { m_style = style; }
+
+void SaveCoreOptions::SetOutputFile(FileSpec file) { m_file = file; }
+
+std::optional<std::string> SaveCoreOptions::GetPluginName() const {
+ return m_plugin_name;
+}
+
+lldb::SaveCoreStyle SaveCoreOptions::GetStyle() const {
+ return m_style.value_or(lldb::eSaveCoreUnspecified);
+}
+
+const std::optional<lldb_private::FileSpec>
+SaveCoreOptions::GetOutputFile() const {
+ return m_file;
+}
+
+void SaveCoreOptions::Clear() {
+ m_file = std::nullopt;
+ m_plugin_name = std::nullopt;
+ m_style = std::nullopt;
+}
diff --git a/lldb/test/API/functionalities/process_save_core/TestProcessSaveCore.py b/lldb/test/API/functionalities/process_save_core/TestProcessSaveCore.py
index c3f0e75..07d06bd 100644
--- a/lldb/test/API/functionalities/process_save_core/TestProcessSaveCore.py
+++ b/lldb/test/API/functionalities/process_save_core/TestProcessSaveCore.py
@@ -2,7 +2,6 @@
Test saving a core file (or mini dump).
"""
-
import os
import lldb
from lldbsuite.test.decorators import *
@@ -21,6 +20,8 @@ class ProcessSaveCoreTestCase(TestBase):
target = self.dbg.CreateTarget(exe)
process = target.LaunchSimple(None, None, self.get_process_working_directory())
self.assertNotEqual(process.GetState(), lldb.eStateStopped)
+ options = SBSaveCoreOptions()
+ options.SetOutputFile(SBFileSpec(core))
error = process.SaveCore(core)
self.assertTrue(error.Fail())
diff --git a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
index 1e171e7..96511d7 100644
--- a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
+++ b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
@@ -132,8 +132,13 @@ class ProcessSaveCoreMinidumpTestCase(TestBase):
stacks_to_sp_map,
)
+ options = lldb.SBSaveCoreOptions()
+ core_sb_stack_spec = lldb.SBFileSpec(core_sb_stack)
+ options.SetOutputFile(core_sb_stack_spec)
+ options.SetPluginName("minidump")
+ options.SetStyle(lldb.eSaveCoreStackOnly)
# validate saving via SBProcess
- error = process.SaveCore(core_sb_stack, "minidump", lldb.eSaveCoreStackOnly)
+ error = process.SaveCore(options)
self.assertTrue(error.Success())
self.assertTrue(os.path.isfile(core_sb_stack))
self.verify_core_file(
@@ -144,7 +149,12 @@ class ProcessSaveCoreMinidumpTestCase(TestBase):
stacks_to_sp_map,
)
- error = process.SaveCore(core_sb_dirty, "minidump", lldb.eSaveCoreDirtyOnly)
+ options = lldb.SBSaveCoreOptions()
+ core_sb_dirty_spec = lldb.SBFileSpec(core_sb_dirty)
+ options.SetOutputFile(core_sb_dirty_spec)
+ options.SetPluginName("minidump")
+ options.SetStyle(lldb.eSaveCoreDirtyOnly)
+ error = process.SaveCore(options)
self.assertTrue(error.Success())
self.assertTrue(os.path.isfile(core_sb_dirty))
self.verify_core_file(
@@ -157,7 +167,12 @@ class ProcessSaveCoreMinidumpTestCase(TestBase):
# Minidump can now save full core files, but they will be huge and
# they might cause this test to timeout.
- error = process.SaveCore(core_sb_full, "minidump", lldb.eSaveCoreFull)
+ options = lldb.SBSaveCoreOptions()
+ core_sb_full_spec = lldb.SBFileSpec(core_sb_full)
+ options.SetOutputFile(core_sb_full_spec)
+ options.SetPluginName("minidump")
+ options.SetStyle(lldb.eSaveCoreFull)
+ error = process.SaveCore(options)
self.assertTrue(error.Success())
self.assertTrue(os.path.isfile(core_sb_full))
self.verify_core_file(
diff --git a/lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py b/lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py
new file mode 100644
index 0000000..c509e81
--- /dev/null
+++ b/lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py
@@ -0,0 +1,28 @@
+"""Test the SBSaveCoreOptions APIs."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class SBSaveCoreOptionsAPICase(TestBase):
+ def test_plugin_name_assignment(self):
+ """Test assignment ensuring valid plugin names only."""
+ options = lldb.SBSaveCoreOptions()
+ error = options.SetPluginName(None)
+ self.assertTrue(error.Success())
+ self.assertEqual(options.GetPluginName(), None)
+ error = options.SetPluginName("Not a real plugin")
+ self.assertTrue(error.Fail())
+ self.assertEqual(options.GetPluginName(), None)
+ error = options.SetPluginName("minidump")
+ self.assertTrue(error.Success())
+ self.assertEqual(options.GetPluginName(), "minidump")
+ error = options.SetPluginName("")
+ self.assertTrue(error.Success())
+ self.assertEqual(options.GetPluginName(), None)
+
+ def test_default_corestyle_behavior(self):
+ """Test that the default core style is unspecified."""
+ options = lldb.SBSaveCoreOptions()
+ self.assertEqual(options.GetStyle(), lldb.eSaveCoreUnspecified)
diff --git a/llvm/docs/CompileCudaWithLLVM.rst b/llvm/docs/CompileCudaWithLLVM.rst
index 0371d7a..1b1a272 100644
--- a/llvm/docs/CompileCudaWithLLVM.rst
+++ b/llvm/docs/CompileCudaWithLLVM.rst
@@ -514,7 +514,7 @@ Modern CPUs and GPUs are architecturally quite different, so code that's fast
on a CPU isn't necessarily fast on a GPU. We've made a number of changes to
LLVM to make it generate good GPU code. Among these changes are:
-* `Straight-line scalar optimizations <https://goo.gl/4Rb9As>`_ -- These
+* `Straight-line scalar optimizations <https://docs.google.com/document/d/1momWzKFf4D6h8H3YlfgKQ3qeZy5ayvMRh6yR-Xn2hUE>`_ -- These
reduce redundancy within straight-line code.
* `Aggressive speculative execution
diff --git a/llvm/include/llvm/CodeGen/TargetCallingConv.h b/llvm/include/llvm/CodeGen/TargetCallingConv.h
index 0ff4e1f..cb00556 100644
--- a/llvm/include/llvm/CodeGen/TargetCallingConv.h
+++ b/llvm/include/llvm/CodeGen/TargetCallingConv.h
@@ -45,9 +45,9 @@ namespace ISD {
unsigned IsHva : 1; ///< HVA field for
unsigned IsHvaStart : 1; ///< HVA structure start
unsigned IsSecArgPass : 1; ///< Second argument
- unsigned MemAlign : 4; ///< Log 2 of alignment when arg is passed in memory
- ///< (including byval/byref). The max alignment is
- ///< verified in IR verification.
+ unsigned MemAlign : 6; ///< Log 2 of alignment when arg is passed in memory
+ ///< (including byval/byref). The max alignment is
+ ///< verified in IR verification.
unsigned OrigAlign : 5; ///< Log 2 of original alignment
unsigned IsInConsecutiveRegsLast : 1;
unsigned IsInConsecutiveRegs : 1;
@@ -67,7 +67,7 @@ namespace ISD {
IsSecArgPass(0), MemAlign(0), OrigAlign(0),
IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
IsCopyElisionCandidate(0), IsPointer(0) {
- static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
+ static_assert(sizeof(*this) == 4 * sizeof(unsigned), "flags are too big");
}
bool isZExt() const { return IsZExt; }
diff --git a/llvm/include/llvm/Object/ArchiveWriter.h b/llvm/include/llvm/Object/ArchiveWriter.h
index e41b3d5..95b81f5 100644
--- a/llvm/include/llvm/Object/ArchiveWriter.h
+++ b/llvm/include/llvm/Object/ArchiveWriter.h
@@ -48,25 +48,30 @@ enum class SymtabWritingMode {
BigArchive64 // Only write the 64-bit symbol table.
};
+void warnToStderr(Error Err);
+
// Write an archive directly to an output stream.
Error writeArchiveToStream(raw_ostream &Out,
ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab,
object::Archive::Kind Kind, bool Deterministic,
- bool Thin, std::optional<bool> IsEC = std::nullopt);
+ bool Thin, std::optional<bool> IsEC = std::nullopt,
+ function_ref<void(Error)> Warn = warnToStderr);
Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin,
std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr,
- std::optional<bool> IsEC = std::nullopt);
+ std::optional<bool> IsEC = std::nullopt,
+ function_ref<void(Error)> Warn = warnToStderr);
// writeArchiveToBuffer is similar to writeArchive but returns the Archive in a
// buffer instead of writing it out to a file.
Expected<std::unique_ptr<MemoryBuffer>>
writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
- bool Deterministic, bool Thin);
+ bool Deterministic, bool Thin,
+ function_ref<void(Error)> Warn = warnToStderr);
}
#endif
diff --git a/llvm/include/llvm/SandboxIR/Tracker.h b/llvm/include/llvm/SandboxIR/Tracker.h
index a91b9f1..b88eb3d 100644
--- a/llvm/include/llvm/SandboxIR/Tracker.h
+++ b/llvm/include/llvm/SandboxIR/Tracker.h
@@ -53,6 +53,7 @@
namespace llvm::sandboxir {
class BasicBlock;
+class Instruction;
class Tracker;
/// The base class for IR Change classes.
@@ -135,6 +136,46 @@ public:
#endif
};
+class RemoveFromParent : public IRChangeBase {
+ /// The instruction that is about to get removed.
+ Instruction *RemovedI = nullptr;
+ /// This is either the next instr, or the parent BB if at the end of the BB.
+ PointerUnion<Instruction *, BasicBlock *> NextInstrOrBB;
+
+public:
+ RemoveFromParent(Instruction *RemovedI, Tracker &Tracker);
+ void revert() final;
+ void accept() final {};
+ Instruction *getInstruction() const { return RemovedI; }
+#ifndef NDEBUG
+ void dump(raw_ostream &OS) const final {
+ dumpCommon(OS);
+ OS << "RemoveFromParent";
+ }
+ LLVM_DUMP_METHOD void dump() const final;
+#endif // NDEBUG
+};
+
+class MoveInstr : public IRChangeBase {
+ /// The instruction that moved.
+ Instruction *MovedI;
+ /// This is either the next instruction in the block, or the parent BB if at
+ /// the end of the BB.
+ PointerUnion<Instruction *, BasicBlock *> NextInstrOrBB;
+
+public:
+ MoveInstr(sandboxir::Instruction *I, Tracker &Tracker);
+ void revert() final;
+ void accept() final {}
+#ifndef NDEBUG
+ void dump(raw_ostream &OS) const final {
+ dumpCommon(OS);
+ OS << "MoveInstr";
+ }
+ LLVM_DUMP_METHOD void dump() const final;
+#endif // NDEBUG
+};
+
/// The tracker collects all the change objects and implements the main API for
/// saving / reverting / accepting.
class Tracker {
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 91994f3..84214c4 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -1730,7 +1730,7 @@ bool MemoryDepChecker::Dependence::isBackward() const {
}
bool MemoryDepChecker::Dependence::isPossiblyBackward() const {
- return isBackward() || Type == Unknown;
+ return isBackward() || Type == Unknown || Type == IndirectUnsafe;
}
bool MemoryDepChecker::Dependence::isForward() const {
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 75a53c1..c5c4076 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -324,13 +324,6 @@ namespace {
class Verifier : public InstVisitor<Verifier>, VerifierSupport {
friend class InstVisitor<Verifier>;
-
- // ISD::ArgFlagsTy::MemAlign only have 4 bits for alignment, so
- // the alignment size should not exceed 2^15. Since encode(Align)
- // would plus the shift value by 1, the alignment size should
- // not exceed 2^14, otherwise it can NOT be properly lowered
- // in backend.
- static constexpr unsigned ParamMaxAlignment = 1 << 14;
DominatorTree DT;
/// When verifying a basic block, keep track of all of the
@@ -2021,31 +2014,43 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
}
if (isa<PointerType>(Ty)) {
+ if (Attrs.hasAttribute(Attribute::Alignment)) {
+ Align AttrAlign = Attrs.getAlignment().valueOrOne();
+ Check(AttrAlign.value() <= Value::MaximumAlignment,
+ "huge alignment values are unsupported", V);
+ }
if (Attrs.hasAttribute(Attribute::ByVal)) {
- if (Attrs.hasAttribute(Attribute::Alignment)) {
- Align AttrAlign = Attrs.getAlignment().valueOrOne();
- Align MaxAlign(ParamMaxAlignment);
- Check(AttrAlign <= MaxAlign,
- "Attribute 'align' exceed the max size 2^14", V);
- }
SmallPtrSet<Type *, 4> Visited;
Check(Attrs.getByValType()->isSized(&Visited),
"Attribute 'byval' does not support unsized types!", V);
+ Check(DL.getTypeAllocSize(Attrs.getByValType()).getKnownMinValue() <
+ (1ULL << 32),
+ "huge 'byval' arguments are unsupported", V);
}
if (Attrs.hasAttribute(Attribute::ByRef)) {
SmallPtrSet<Type *, 4> Visited;
Check(Attrs.getByRefType()->isSized(&Visited),
"Attribute 'byref' does not support unsized types!", V);
+ Check(DL.getTypeAllocSize(Attrs.getByRefType()).getKnownMinValue() <
+ (1ULL << 32),
+ "huge 'byref' arguments are unsupported", V);
}
if (Attrs.hasAttribute(Attribute::InAlloca)) {
SmallPtrSet<Type *, 4> Visited;
Check(Attrs.getInAllocaType()->isSized(&Visited),
"Attribute 'inalloca' does not support unsized types!", V);
+ Check(DL.getTypeAllocSize(Attrs.getInAllocaType()).getKnownMinValue() <
+ (1ULL << 32),
+ "huge 'inalloca' arguments are unsupported", V);
}
if (Attrs.hasAttribute(Attribute::Preallocated)) {
SmallPtrSet<Type *, 4> Visited;
Check(Attrs.getPreallocatedType()->isSized(&Visited),
"Attribute 'preallocated' does not support unsized types!", V);
+ Check(
+ DL.getTypeAllocSize(Attrs.getPreallocatedType()).getKnownMinValue() <
+ (1ULL << 32),
+ "huge 'preallocated' arguments are unsupported", V);
}
}
@@ -3511,12 +3516,15 @@ void Verifier::visitCallBase(CallBase &Call) {
"not allowed. Please use the @llvm.amdgpu.cs.chain intrinsic instead.",
Call);
+ // Disallow passing/returning values with alignment higher than we can
+ // represent.
+ // FIXME: Consider making DataLayout cap the alignment, so this isn't
+ // necessary.
auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) {
if (!Ty->isSized())
return;
Align ABIAlign = DL.getABITypeAlign(Ty);
- Align MaxAlign(ParamMaxAlignment);
- Check(ABIAlign <= MaxAlign,
+ Check(ABIAlign.value() <= Value::MaximumAlignment,
"Incorrect alignment of " + Message + " to called function!", Call);
};
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index 34f12cf..1140455 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -482,7 +482,8 @@ static uint64_t computeHeadersSize(object::Archive::Kind Kind,
}
static Expected<std::unique_ptr<SymbolicFile>>
-getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) {
+getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context,
+ object::Archive::Kind Kind, function_ref<void(Error)> Warn) {
const file_magic Type = identify_magic(Buf.getBuffer());
// Don't attempt to read non-symbolic file types.
if (!object::SymbolicFile::isSymbolicFile(Type, &Context))
@@ -490,8 +491,36 @@ getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) {
if (Type == file_magic::bitcode) {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
Buf, file_magic::bitcode, &Context);
- if (!ObjOrErr)
- return ObjOrErr.takeError();
+ // An error reading a bitcode file most likely indicates that the file
+ // was created by a compiler from the future. Normally we don't try to
+ // implement forwards compatibility for bitcode files, but when creating an
+ // archive we can implement best-effort forwards compatibility by treating
+ // the file as a blob and not creating symbol index entries for it. lld and
+ // mold ignore the archive symbol index, so provided that you use one of
+ // these linkers, LTO will work as long as lld or the gold plugin is newer
+ // than the compiler. We only ignore errors if the archive format is one
+ // that is supported by a linker that is known to ignore the index,
+ // otherwise there's no chance of this working so we may as well error out.
+ // We print a warning on read failure so that users of linkers that rely on
+ // the symbol index can diagnose the issue.
+ //
+ // This is the same behavior as GNU ar when the linker plugin returns an
+ // error when reading the input file. If the bitcode file is actually
+ // malformed, it will be diagnosed at link time.
+ if (!ObjOrErr) {
+ switch (Kind) {
+ case object::Archive::K_BSD:
+ case object::Archive::K_GNU:
+ case object::Archive::K_GNU64:
+ Warn(ObjOrErr.takeError());
+ return nullptr;
+ case object::Archive::K_AIXBIG:
+ case object::Archive::K_COFF:
+ case object::Archive::K_DARWIN:
+ case object::Archive::K_DARWIN64:
+ return ObjOrErr.takeError();
+ }
+ }
return std::move(*ObjOrErr);
} else {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
@@ -751,7 +780,7 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
object::Archive::Kind Kind, bool Thin, bool Deterministic,
SymtabWritingMode NeedSymbols, SymMap *SymMap,
LLVMContext &Context, ArrayRef<NewArchiveMember> NewMembers,
- std::optional<bool> IsEC) {
+ std::optional<bool> IsEC, function_ref<void(Error)> Warn) {
static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
uint64_t MemHeadPadSize = 0;
uint64_t Pos =
@@ -819,8 +848,10 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
if (NeedSymbols != SymtabWritingMode::NoSymtab || isAIXBigArchive(Kind)) {
for (const NewArchiveMember &M : NewMembers) {
- Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr =
- getSymbolicFile(M.Buf->getMemBufferRef(), Context);
+ Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr = getSymbolicFile(
+ M.Buf->getMemBufferRef(), Context, Kind, [&](Error Err) {
+ Warn(createFileError(M.MemberName, std::move(Err)));
+ });
if (!SymFileOrErr)
return createFileError(M.MemberName, SymFileOrErr.takeError());
SymFiles.push_back(std::move(*SymFileOrErr));
@@ -1001,7 +1032,8 @@ Error writeArchiveToStream(raw_ostream &Out,
ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab,
object::Archive::Kind Kind, bool Deterministic,
- bool Thin, std::optional<bool> IsEC) {
+ bool Thin, std::optional<bool> IsEC,
+ function_ref<void(Error)> Warn) {
assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
SmallString<0> SymNamesBuf;
@@ -1023,7 +1055,7 @@ Error writeArchiveToStream(raw_ostream &Out,
Expected<std::vector<MemberData>> DataOrErr = computeMemberData(
StringTable, SymNames, Kind, Thin, Deterministic, WriteSymtab,
- isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers, IsEC);
+ isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers, IsEC, Warn);
if (Error E = DataOrErr.takeError())
return E;
std::vector<MemberData> &Data = *DataOrErr;
@@ -1266,11 +1298,15 @@ Error writeArchiveToStream(raw_ostream &Out,
return Error::success();
}
+void warnToStderr(Error Err) {
+ llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "warning: ");
+}
+
Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin,
std::unique_ptr<MemoryBuffer> OldArchiveBuf,
- std::optional<bool> IsEC) {
+ std::optional<bool> IsEC, function_ref<void(Error)> Warn) {
Expected<sys::fs::TempFile> Temp =
sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");
if (!Temp)
@@ -1278,7 +1314,7 @@ Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
raw_fd_ostream Out(Temp->FD, false);
if (Error E = writeArchiveToStream(Out, NewMembers, WriteSymtab, Kind,
- Deterministic, Thin, IsEC)) {
+ Deterministic, Thin, IsEC, Warn)) {
if (Error DiscardError = Temp->discard())
return joinErrors(std::move(E), std::move(DiscardError));
return E;
@@ -1302,12 +1338,14 @@ Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
Expected<std::unique_ptr<MemoryBuffer>>
writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
- bool Deterministic, bool Thin) {
+ bool Deterministic, bool Thin,
+ function_ref<void(Error)> Warn) {
SmallVector<char, 0> ArchiveBufferVector;
raw_svector_ostream ArchiveStream(ArchiveBufferVector);
- if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab,
- Kind, Deterministic, Thin, std::nullopt))
+ if (Error E =
+ writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab, Kind,
+ Deterministic, Thin, std::nullopt, Warn))
return std::move(E);
return std::make_unique<SmallVectorMemoryBuffer>(
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index c6daf1a..8713499 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -333,6 +333,10 @@ Instruction *Instruction::getPrevNode() const {
}
void Instruction::removeFromParent() {
+ auto &Tracker = Ctx.getTracker();
+ if (Tracker.isTracking())
+ Tracker.track(std::make_unique<RemoveFromParent>(this, Tracker));
+
// Detach all the LLVM IR instructions from their parent BB.
for (llvm::Instruction *I : getLLVMInstrs())
I->removeFromParent();
@@ -367,6 +371,11 @@ void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) {
if (std::next(getIterator()) == WhereIt)
// Destination is same as origin, nothing to do.
return;
+
+ auto &Tracker = Ctx.getTracker();
+ if (Tracker.isTracking())
+ Tracker.track(std::make_unique<MoveInstr>(this, Tracker));
+
auto *LLVMBB = cast<llvm::BasicBlock>(BB.Val);
llvm::BasicBlock::iterator It;
if (WhereIt == BB.end()) {
diff --git a/llvm/lib/SandboxIR/Tracker.cpp b/llvm/lib/SandboxIR/Tracker.cpp
index 2336a00..626c9c2 100644
--- a/llvm/lib/SandboxIR/Tracker.cpp
+++ b/llvm/lib/SandboxIR/Tracker.cpp
@@ -98,6 +98,54 @@ void EraseFromParent::dump() const {
dump(dbgs());
dbgs() << "\n";
}
+#endif // NDEBUG
+
+RemoveFromParent::RemoveFromParent(Instruction *RemovedI, Tracker &Tracker)
+ : IRChangeBase(Tracker), RemovedI(RemovedI) {
+ if (auto *NextI = RemovedI->getNextNode())
+ NextInstrOrBB = NextI;
+ else
+ NextInstrOrBB = RemovedI->getParent();
+}
+
+void RemoveFromParent::revert() {
+ if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
+ RemovedI->insertBefore(NextI);
+ } else {
+ auto *BB = NextInstrOrBB.get<BasicBlock *>();
+ RemovedI->insertInto(BB, BB->end());
+ }
+}
+
+#ifndef NDEBUG
+void RemoveFromParent::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
+#endif
+
+MoveInstr::MoveInstr(Instruction *MovedI, Tracker &Tracker)
+ : IRChangeBase(Tracker), MovedI(MovedI) {
+ if (auto *NextI = MovedI->getNextNode())
+ NextInstrOrBB = NextI;
+ else
+ NextInstrOrBB = MovedI->getParent();
+}
+
+void MoveInstr::revert() {
+ if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
+ MovedI->moveBefore(NextI);
+ } else {
+ auto *BB = NextInstrOrBB.get<BasicBlock *>();
+ MovedI->moveBefore(*BB, BB->end());
+ }
+}
+
+#ifndef NDEBUG
+void MoveInstr::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
#endif
void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {
diff --git a/llvm/lib/Target/AMDGPU/FLATInstructions.td b/llvm/lib/Target/AMDGPU/FLATInstructions.td
index 56cc6ff..88c6039 100644
--- a/llvm/lib/Target/AMDGPU/FLATInstructions.td
+++ b/llvm/lib/Target/AMDGPU/FLATInstructions.td
@@ -1589,15 +1589,13 @@ let OtherPredicates = [isGFX12Plus] in {
let WaveSizePredicate = isWave32 in {
defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B64_w32, int_amdgcn_global_load_tr_b64, v2i32>;
- defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr_b128, v8i16>;
- defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr_b128, v8f16>;
- defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr_b128, v8bf16>;
+ foreach vt = [v8i16, v8f16, v8bf16] in
+ defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr_b128, vt>;
}
let WaveSizePredicate = isWave64 in {
defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B64_w64, int_amdgcn_global_load_tr_b64, i32>;
- defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr_b128, v4i16>;
- defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr_b128, v4f16>;
- defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr_b128, v4bf16>;
+ foreach vt = [v4i16, v4f16, v4bf16] in
+ defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr_b128, vt>;
}
}
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index c7d41f6..9bda288 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -11,11 +11,11 @@
/// reads.
///
/// The algorithm of the tool is similar to Memcheck
-/// (http://goo.gl/QKbem). We associate a few shadow bits with every
-/// byte of the application memory, poison the shadow of the malloc-ed
-/// or alloca-ed memory, load the shadow bits on every memory read,
-/// propagate the shadow bits through some of the arithmetic
-/// instruction (including MOV), store the shadow bits on every memory
+/// (https://static.usenix.org/event/usenix05/tech/general/full_papers/seward/seward_html/usenix2005.html)
+/// We associate a few shadow bits with every byte of the application memory,
+/// poison the shadow of the malloc-ed or alloca-ed memory, load the shadow,
+/// bits on every memory read, propagate the shadow bits through some of the
+/// arithmetic instruction (including MOV), store the shadow bits on every memory
/// write, report a bug on some other instructions (e.g. JMP) if the
/// associated shadow is poisoned.
///
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 748db41..fbca4cd 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -2767,18 +2767,17 @@ InnerLoopVectorizer::getOrCreateVectorTripCount(BasicBlock *InsertBlock) {
Value *InnerLoopVectorizer::createBitOrPointerCast(Value *V, VectorType *DstVTy,
const DataLayout &DL) {
// Verify that V is a vector type with same number of elements as DstVTy.
- auto *DstFVTy = cast<VectorType>(DstVTy);
- auto VF = DstFVTy->getElementCount();
+ auto VF = DstVTy->getElementCount();
auto *SrcVecTy = cast<VectorType>(V->getType());
assert(VF == SrcVecTy->getElementCount() && "Vector dimensions do not match");
Type *SrcElemTy = SrcVecTy->getElementType();
- Type *DstElemTy = DstFVTy->getElementType();
+ Type *DstElemTy = DstVTy->getElementType();
assert((DL.getTypeSizeInBits(SrcElemTy) == DL.getTypeSizeInBits(DstElemTy)) &&
"Vector elements must have same size");
// Do a direct cast if element types are castable.
if (CastInst::isBitOrNoopPointerCastable(SrcElemTy, DstElemTy, DL)) {
- return Builder.CreateBitOrPointerCast(V, DstFVTy);
+ return Builder.CreateBitOrPointerCast(V, DstVTy);
}
// V cannot be directly casted to desired vector type.
// May happen when V is a floating point vector but DstVTy is a vector of
@@ -2792,7 +2791,7 @@ Value *InnerLoopVectorizer::createBitOrPointerCast(Value *V, VectorType *DstVTy,
IntegerType::getIntNTy(V->getContext(), DL.getTypeSizeInBits(SrcElemTy));
auto *VecIntTy = VectorType::get(IntTy, VF);
Value *CastVal = Builder.CreateBitOrPointerCast(V, VecIntTy);
- return Builder.CreateBitOrPointerCast(CastVal, DstFVTy);
+ return Builder.CreateBitOrPointerCast(CastVal, DstVTy);
}
void InnerLoopVectorizer::emitIterationCountCheck(BasicBlock *Bypass) {
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 3a49f95..4445985 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -117,7 +117,7 @@ private:
bool foldShuffleOfShuffles(Instruction &I);
bool foldShuffleToIdentity(Instruction &I);
bool foldShuffleFromReductions(Instruction &I);
- bool foldTruncFromReductions(Instruction &I);
+ bool foldCastFromReductions(Instruction &I);
bool foldSelectShuffle(Instruction &I, bool FromReduction = false);
void replaceValue(Value &Old, Value &New) {
@@ -2113,15 +2113,20 @@ bool VectorCombine::foldShuffleFromReductions(Instruction &I) {
/// Determine if its more efficient to fold:
/// reduce(trunc(x)) -> trunc(reduce(x)).
-bool VectorCombine::foldTruncFromReductions(Instruction &I) {
+/// reduce(sext(x)) -> sext(reduce(x)).
+/// reduce(zext(x)) -> zext(reduce(x)).
+bool VectorCombine::foldCastFromReductions(Instruction &I) {
auto *II = dyn_cast<IntrinsicInst>(&I);
if (!II)
return false;
+ bool TruncOnly = false;
Intrinsic::ID IID = II->getIntrinsicID();
switch (IID) {
case Intrinsic::vector_reduce_add:
case Intrinsic::vector_reduce_mul:
+ TruncOnly = true;
+ break;
case Intrinsic::vector_reduce_and:
case Intrinsic::vector_reduce_or:
case Intrinsic::vector_reduce_xor:
@@ -2133,35 +2138,37 @@ bool VectorCombine::foldTruncFromReductions(Instruction &I) {
unsigned ReductionOpc = getArithmeticReductionInstruction(IID);
Value *ReductionSrc = I.getOperand(0);
- Value *TruncSrc;
- if (!match(ReductionSrc, m_OneUse(m_Trunc(m_Value(TruncSrc)))))
+ Value *Src;
+ if (!match(ReductionSrc, m_OneUse(m_Trunc(m_Value(Src)))) &&
+ (TruncOnly || !match(ReductionSrc, m_OneUse(m_ZExtOrSExt(m_Value(Src))))))
return false;
- auto *TruncSrcTy = cast<VectorType>(TruncSrc->getType());
+ auto CastOpc =
+ (Instruction::CastOps)cast<Instruction>(ReductionSrc)->getOpcode();
+
+ auto *SrcTy = cast<VectorType>(Src->getType());
auto *ReductionSrcTy = cast<VectorType>(ReductionSrc->getType());
Type *ResultTy = I.getType();
TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
InstructionCost OldCost = TTI.getArithmeticReductionCost(
ReductionOpc, ReductionSrcTy, std::nullopt, CostKind);
- if (auto *Trunc = dyn_cast<CastInst>(ReductionSrc))
- OldCost +=
- TTI.getCastInstrCost(Instruction::Trunc, ReductionSrcTy, TruncSrcTy,
- TTI::CastContextHint::None, CostKind, Trunc);
+ OldCost += TTI.getCastInstrCost(CastOpc, ReductionSrcTy, SrcTy,
+ TTI::CastContextHint::None, CostKind,
+ cast<CastInst>(ReductionSrc));
InstructionCost NewCost =
- TTI.getArithmeticReductionCost(ReductionOpc, TruncSrcTy, std::nullopt,
+ TTI.getArithmeticReductionCost(ReductionOpc, SrcTy, std::nullopt,
CostKind) +
- TTI.getCastInstrCost(Instruction::Trunc, ResultTy,
- ReductionSrcTy->getScalarType(),
+ TTI.getCastInstrCost(CastOpc, ResultTy, ReductionSrcTy->getScalarType(),
TTI::CastContextHint::None, CostKind);
if (OldCost <= NewCost || !NewCost.isValid())
return false;
- Value *NewReduction = Builder.CreateIntrinsic(
- TruncSrcTy->getScalarType(), II->getIntrinsicID(), {TruncSrc});
- Value *NewTruncation = Builder.CreateTrunc(NewReduction, ResultTy);
- replaceValue(I, *NewTruncation);
+ Value *NewReduction = Builder.CreateIntrinsic(SrcTy->getScalarType(),
+ II->getIntrinsicID(), {Src});
+ Value *NewCast = Builder.CreateCast(CastOpc, NewReduction, ResultTy);
+ replaceValue(I, *NewCast);
return true;
}
@@ -2559,7 +2566,7 @@ bool VectorCombine::run() {
switch (Opcode) {
case Instruction::Call:
MadeChange |= foldShuffleFromReductions(I);
- MadeChange |= foldTruncFromReductions(I);
+ MadeChange |= foldCastFromReductions(I);
break;
case Instruction::ICmp:
case Instruction::FCmp:
diff --git a/llvm/test/Instrumentation/MemorySanitizer/AArch64/neon_vst_origins.ll b/llvm/test/Instrumentation/MemorySanitizer/AArch64/neon_vst_origins.ll
new file mode 100644
index 0000000..ff4c4c2
--- /dev/null
+++ b/llvm/test/Instrumentation/MemorySanitizer/AArch64/neon_vst_origins.ll
@@ -0,0 +1,158 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; Test memory sanitizer instrumentation for Arm NEON VST instructions, with
+; origin tracking. These tests are deliberately shorter than neon_vst.ll, due
+; to the verbosity of the output.
+;
+; RUN: opt < %s -passes=msan -msan-track-origins=2 -S | FileCheck %s
+;
+; Forked from llvm/test/CodeGen/AArch64/arm64-st1.ll
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-android9001"
+
+; -----------------------------------------------------------------------------------------------------------------------------------------------
+
+define void @st2_16b(<16 x i8> %A, <16 x i8> %B, ptr %P) nounwind sanitize_memory {
+;
+; CHECK-LABEL: define void @st2_16b
+; CHECK-SAME: (<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i8>, ptr @__msan_param_tls, align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @__msan_param_origin_tls, align 4
+; CHECK-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
+; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 16) to ptr), align 4
+; CHECK-NEXT: [[TMP5:%.*]] = load i64, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 32) to ptr), align 8
+; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 32) to ptr), align 4
+; CHECK-NEXT: call void @llvm.donothing()
+; CHECK-NEXT: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP1]] to i128
+; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP7]], 0
+; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP8:%.*]], label [[TMP9:%.*]], !prof [[PROF0:![0-9]+]]
+; CHECK: 8:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP2]]) #[[ATTR4:[0-9]+]]
+; CHECK-NEXT: unreachable
+; CHECK: 9:
+; CHECK-NEXT: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP3]] to i128
+; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP10]], 0
+; CHECK-NEXT: br i1 [[_MSCMP1]], label [[TMP11:%.*]], label [[TMP12:%.*]], !prof [[PROF0]]
+; CHECK: 11:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP4]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 12:
+; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i64 [[TMP5]], 0
+; CHECK-NEXT: br i1 [[_MSCMP2]], label [[TMP13:%.*]], label [[TMP14:%.*]], !prof [[PROF0]]
+; CHECK: 13:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP6]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 14:
+; CHECK-NEXT: call void @llvm.aarch64.neon.st2.v16i8.p0(<16 x i8> [[A]], <16 x i8> [[B]], ptr [[P]])
+; CHECK-NEXT: ret void
+;
+ call void @llvm.aarch64.neon.st2.v16i8.p0(<16 x i8> %A, <16 x i8> %B, ptr %P)
+ ret void
+}
+
+define void @st3_16b(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, ptr %P) nounwind sanitize_memory {
+;
+; CHECK-LABEL: define void @st3_16b
+; CHECK-SAME: (<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], <16 x i8> [[C:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i8>, ptr @__msan_param_tls, align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @__msan_param_origin_tls, align 4
+; CHECK-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
+; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 16) to ptr), align 4
+; CHECK-NEXT: [[TMP5:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 32) to ptr), align 8
+; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 32) to ptr), align 4
+; CHECK-NEXT: [[TMP7:%.*]] = load i64, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 48) to ptr), align 8
+; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 48) to ptr), align 4
+; CHECK-NEXT: call void @llvm.donothing()
+; CHECK-NEXT: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP1]] to i128
+; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP9]], 0
+; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP10:%.*]], label [[TMP11:%.*]], !prof [[PROF0]]
+; CHECK: 10:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP2]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 11:
+; CHECK-NEXT: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP3]] to i128
+; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP12]], 0
+; CHECK-NEXT: br i1 [[_MSCMP1]], label [[TMP13:%.*]], label [[TMP14:%.*]], !prof [[PROF0]]
+; CHECK: 13:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP4]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 14:
+; CHECK-NEXT: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP5]] to i128
+; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i128 [[TMP15]], 0
+; CHECK-NEXT: br i1 [[_MSCMP2]], label [[TMP16:%.*]], label [[TMP17:%.*]], !prof [[PROF0]]
+; CHECK: 16:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP6]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 17:
+; CHECK-NEXT: [[_MSCMP3:%.*]] = icmp ne i64 [[TMP7]], 0
+; CHECK-NEXT: br i1 [[_MSCMP3]], label [[TMP18:%.*]], label [[TMP19:%.*]], !prof [[PROF0]]
+; CHECK: 18:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP8]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 19:
+; CHECK-NEXT: call void @llvm.aarch64.neon.st3.v16i8.p0(<16 x i8> [[A]], <16 x i8> [[B]], <16 x i8> [[C]], ptr [[P]])
+; CHECK-NEXT: ret void
+;
+ call void @llvm.aarch64.neon.st3.v16i8.p0(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, ptr %P)
+ ret void
+}
+
+define void @st4_16b(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, <16 x i8> %D, ptr %P) nounwind sanitize_memory {
+;
+; CHECK-LABEL: define void @st4_16b
+; CHECK-SAME: (<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], <16 x i8> [[C:%.*]], <16 x i8> [[D:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i8>, ptr @__msan_param_tls, align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @__msan_param_origin_tls, align 4
+; CHECK-NEXT: [[TMP3:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
+; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 16) to ptr), align 4
+; CHECK-NEXT: [[TMP5:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 32) to ptr), align 8
+; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 32) to ptr), align 4
+; CHECK-NEXT: [[TMP7:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 48) to ptr), align 8
+; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 48) to ptr), align 4
+; CHECK-NEXT: [[TMP9:%.*]] = load i64, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 64) to ptr), align 8
+; CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_origin_tls to i64), i64 64) to ptr), align 4
+; CHECK-NEXT: call void @llvm.donothing()
+; CHECK-NEXT: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP1]] to i128
+; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP11]], 0
+; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP12:%.*]], label [[TMP13:%.*]], !prof [[PROF0]]
+; CHECK: 12:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP2]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 13:
+; CHECK-NEXT: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP3]] to i128
+; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP14]], 0
+; CHECK-NEXT: br i1 [[_MSCMP1]], label [[TMP15:%.*]], label [[TMP16:%.*]], !prof [[PROF0]]
+; CHECK: 15:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP4]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 16:
+; CHECK-NEXT: [[TMP17:%.*]] = bitcast <16 x i8> [[TMP5]] to i128
+; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i128 [[TMP17]], 0
+; CHECK-NEXT: br i1 [[_MSCMP2]], label [[TMP18:%.*]], label [[TMP19:%.*]], !prof [[PROF0]]
+; CHECK: 18:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP6]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 19:
+; CHECK-NEXT: [[TMP20:%.*]] = bitcast <16 x i8> [[TMP7]] to i128
+; CHECK-NEXT: [[_MSCMP3:%.*]] = icmp ne i128 [[TMP20]], 0
+; CHECK-NEXT: br i1 [[_MSCMP3]], label [[TMP21:%.*]], label [[TMP22:%.*]], !prof [[PROF0]]
+; CHECK: 21:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP8]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 22:
+; CHECK-NEXT: [[_MSCMP4:%.*]] = icmp ne i64 [[TMP9]], 0
+; CHECK-NEXT: br i1 [[_MSCMP4]], label [[TMP23:%.*]], label [[TMP24:%.*]], !prof [[PROF0]]
+; CHECK: 23:
+; CHECK-NEXT: call void @__msan_warning_with_origin_noreturn(i32 [[TMP10]]) #[[ATTR4]]
+; CHECK-NEXT: unreachable
+; CHECK: 24:
+; CHECK-NEXT: call void @llvm.aarch64.neon.st4.v16i8.p0(<16 x i8> [[A]], <16 x i8> [[B]], <16 x i8> [[C]], <16 x i8> [[D]], ptr [[P]])
+; CHECK-NEXT: ret void
+;
+ call void @llvm.aarch64.neon.st4.v16i8.p0(<16 x i8> %A, <16 x i8> %B, <16 x i8> %C, <16 x i8> %D, ptr %P)
+ ret void
+}
+
+declare void @llvm.aarch64.neon.st2.v16i8.p0(<16 x i8>, <16 x i8>, ptr) nounwind sanitize_memory readonly
+declare void @llvm.aarch64.neon.st3.v16i8.p0(<16 x i8>, <16 x i8>, <16 x i8>, ptr) nounwind sanitize_memory readonly
+declare void @llvm.aarch64.neon.st4.v16i8.p0(<16 x i8>, <16 x i8>, <16 x i8>, <16 x i8>, ptr) nounwind sanitize_memory readonly
diff --git a/llvm/test/MC/AArch64/elf-reloc-ptrauth.s b/llvm/test/MC/AArch64/elf-reloc-ptrauth.s
index 3bd8f5c..057b298 100644
--- a/llvm/test/MC/AArch64/elf-reloc-ptrauth.s
+++ b/llvm/test/MC/AArch64/elf-reloc-ptrauth.s
@@ -3,16 +3,16 @@
// RUN: llvm-mc -triple=aarch64 -filetype=obj %s | \
// RUN: llvm-readelf -S -r -x .test - | FileCheck %s --check-prefix=RELOC
-// RELOC: Relocation section '.rela.test' at offset 0x230 contains 8 entries:
+// RELOC: Relocation section '.rela.test' at offset {{.*}} contains 8 entries:
// RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
-// RELOC-NEXT: 0000000000000000 0000000100000244 R_AARCH64_AUTH_ABS64 0000000000000000 .helper + 0
-// RELOC-NEXT: 0000000000000010 0000000800000244 R_AARCH64_AUTH_ABS64 0000000000000000 _g1 + 0
-// RELOC-NEXT: 0000000000000020 0000000900000244 R_AARCH64_AUTH_ABS64 0000000000000000 _g2 + 0
-// RELOC-NEXT: 0000000000000030 0000000a00000244 R_AARCH64_AUTH_ABS64 0000000000000000 _g3 + 0
-// RELOC-NEXT: 0000000000000040 0000000b00000244 R_AARCH64_AUTH_ABS64 0000000000000000 _g4 + 7
-// RELOC-NEXT: 0000000000000050 0000000c00000244 R_AARCH64_AUTH_ABS64 0000000000000000 _g5 - 3
-// RELOC-NEXT: 0000000000000060 0000000200000244 R_AARCH64_AUTH_ABS64 0000000000000000 _g 6 + 0
-// RELOC-NEXT: 0000000000000070 0000000d00000244 R_AARCH64_AUTH_ABS64 0000000000000000 _g 7 + 7
+// RELOC-NEXT: 0000000000000000 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 .helper + 0
+// RELOC-NEXT: 0000000000000010 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 _g1 + 0
+// RELOC-NEXT: 0000000000000020 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 _g2 + 0
+// RELOC-NEXT: 0000000000000030 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 _g3 + 0
+// RELOC-NEXT: 0000000000000040 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 _g4 + 7
+// RELOC-NEXT: 0000000000000050 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 _g5 - 3
+// RELOC-NEXT: 0000000000000060 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 _g 6 + 0
+// RELOC-NEXT: 0000000000000070 {{.*}} R_AARCH64_AUTH_ABS64 0000000000000000 _g 7 + 7
// RELOC: Hex dump of section '.test':
// VVVVVVVV addend, not needed for rela
diff --git a/llvm/test/Object/archive-malformed-object.test b/llvm/test/Object/archive-malformed-object.test
index a927629..021df7e 100644
--- a/llvm/test/Object/archive-malformed-object.test
+++ b/llvm/test/Object/archive-malformed-object.test
@@ -1,27 +1,51 @@
## Show that the archive library emits error messages when adding malformed
-## objects.
+## object files and skips symbol tables for "malformed" bitcode files, which
+## are assumed to be bitcode files generated by compilers from the future.
# RUN: rm -rf %t.dir
# RUN: split-file %s %t.dir
# RUN: cd %t.dir
-## Malformed bitcode object is the first file member of archive if the symbol table is required.
+## Create a malformed bitcode object.
# RUN: llvm-as input.ll -o input.bc
# RUN: cp input.bc good.bc
# RUN: %python -c "with open('input.bc', 'a') as f: f.truncate(10)"
-# RUN: not llvm-ar rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
-## Malformed bitcode object is the last file member of archive if the symbol table is required.
+## Malformed bitcode objects either warn or error depending on the archive format
+## (see switch in getSymbolicFile). If the archive was created with a warning,
+## we want to check that the archive map is empty. llvm-nm will fail when it
+## tries to read the malformed bitcode file, but it's supposed to print the
+## archive map first, which in this case it won't because there won't be one.
# RUN: rm -rf bad.a
-# RUN: not llvm-ar rc bad.a good.bc input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+# RUN: llvm-ar --format=bsd rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=WARN1
+# RUN: not llvm-nm --print-armap bad.a | count 0
+# RUN: rm -rf bad.a
+# RUN: llvm-ar --format=gnu rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=WARN1
+# RUN: not llvm-nm --print-armap bad.a | count 0
+# RUN: rm -rf bad.a
+# RUN: not llvm-ar --format=bigarchive rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+# RUN: rm -rf bad.a
+# RUN: not llvm-ar --format=coff rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+# RUN: rm -rf bad.a
+# RUN: not llvm-ar --format=darwin rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+
+## Malformed bitcode object is the last file member of archive and
+## the symbol table is required. In this case we check that the
+## symbol table contains entries for the good object only.
+# RUN: rm -rf bad.a
+# RUN: llvm-ar rc bad.a good.bc input.bc 2>&1 | FileCheck %s --check-prefix=WARN1
+# RUN: not llvm-nm --print-armap bad.a | FileCheck %s --check-prefix=ARMAP
## Malformed bitcode object if the symbol table is not required for big archive.
+## For big archives we print an error instead of a warning because the AIX linker
+## presumably requires the index.
# RUN: rm -rf bad.a
# RUN: not llvm-ar --format=bigarchive rcS bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
# RUN: rm -rf bad.a
# RUN: not llvm-ar --format=bigarchive rcS bad.a good.bc input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
# ERR1: error: bad.a: 'input.bc': Invalid bitcode signature
+# WARN1: warning: 'input.bc': Invalid bitcode signature
## Non-bitcode malformed file.
# RUN: yaml2obj input.yaml -o input.o
@@ -29,17 +53,23 @@
# ERR2: error: bad.a: 'input.o': section header table goes past the end of the file: e_shoff = 0x9999
-## Don't emit an error if the symbol table is not required for formats other than the big archive format.
-# RUN: llvm-ar --format=gnu rcS good.a input.o input.bc
+## Don't emit an error or warning if the symbol table is not required for formats other than the big archive format.
+# RUN: llvm-ar --format=gnu rcS good.a input.o input.bc 2>&1 | count 0
# RUN: llvm-ar t good.a | FileCheck %s --check-prefix=CONTENTS
# CONTENTS: input.o
# CONTENTS-NEXT: input.bc
+# ARMAP: Archive map
+# ARMAP-NEXT: foo in good.bc
+# ARMAP-EMPTY:
+
#--- input.ll
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux"
+@foo = global i32 1
+
#--- input.yaml
--- !ELF
FileHeader:
diff --git a/llvm/test/Transforms/VectorCombine/RISCV/vecreduce-of-cast.ll b/llvm/test/Transforms/VectorCombine/RISCV/vecreduce-of-cast.ll
index 9b1aa19..f04bcc9 100644
--- a/llvm/test/Transforms/VectorCombine/RISCV/vecreduce-of-cast.ll
+++ b/llvm/test/Transforms/VectorCombine/RISCV/vecreduce-of-cast.ll
@@ -74,8 +74,8 @@ define i16 @reduce_mul_trunc_v8i64_i16(<8 x i64> %a0) {
define i32 @reduce_or_sext_v8i8_to_v8i32(<8 x i8> %a0) {
; CHECK-LABEL: @reduce_or_sext_v8i8_to_v8i32(
-; CHECK-NEXT: [[TR:%.*]] = sext <8 x i8> [[A0:%.*]] to <8 x i32>
-; CHECK-NEXT: [[RED:%.*]] = tail call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> [[TR]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.vector.reduce.or.v8i8(<8 x i8> [[A0:%.*]])
+; CHECK-NEXT: [[RED:%.*]] = sext i8 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[RED]]
;
%tr = sext <8 x i8> %a0 to <8 x i32>
@@ -85,8 +85,8 @@ define i32 @reduce_or_sext_v8i8_to_v8i32(<8 x i8> %a0) {
define i32 @reduce_or_sext_v8i16_to_v8i32(<8 x i16> %a0) {
; CHECK-LABEL: @reduce_or_sext_v8i16_to_v8i32(
-; CHECK-NEXT: [[TR:%.*]] = sext <8 x i16> [[A0:%.*]] to <8 x i32>
-; CHECK-NEXT: [[RED:%.*]] = tail call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> [[TR]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.vector.reduce.or.v8i16(<8 x i16> [[A0:%.*]])
+; CHECK-NEXT: [[RED:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[RED]]
;
%tr = sext <8 x i16> %a0 to <8 x i32>
@@ -96,8 +96,8 @@ define i32 @reduce_or_sext_v8i16_to_v8i32(<8 x i16> %a0) {
define i32 @reduce_or_zext_v8i8_to_v8i32(<8 x i8> %a0) {
; CHECK-LABEL: @reduce_or_zext_v8i8_to_v8i32(
-; CHECK-NEXT: [[TR:%.*]] = zext <8 x i8> [[A0:%.*]] to <8 x i32>
-; CHECK-NEXT: [[RED:%.*]] = tail call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> [[TR]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.vector.reduce.or.v8i8(<8 x i8> [[A0:%.*]])
+; CHECK-NEXT: [[RED:%.*]] = zext i8 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[RED]]
;
%tr = zext <8 x i8> %a0 to <8 x i32>
@@ -107,8 +107,8 @@ define i32 @reduce_or_zext_v8i8_to_v8i32(<8 x i8> %a0) {
define i32 @reduce_or_zext_v8i16_to_v8i32(<8 x i16> %a0) {
; CHECK-LABEL: @reduce_or_zext_v8i16_to_v8i32(
-; CHECK-NEXT: [[TR:%.*]] = zext <8 x i16> [[A0:%.*]] to <8 x i32>
-; CHECK-NEXT: [[RED:%.*]] = tail call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> [[TR]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.vector.reduce.or.v8i16(<8 x i16> [[A0:%.*]])
+; CHECK-NEXT: [[RED:%.*]] = zext i16 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[RED]]
;
%tr = zext <8 x i16> %a0 to <8 x i32>
@@ -116,6 +116,20 @@ define i32 @reduce_or_zext_v8i16_to_v8i32(<8 x i16> %a0) {
ret i32 %red
}
+; Negative case - narrowing the reduce (to i8) is illegal.
+; TODO: We could narrow to i16 instead.
+define i32 @reduce_add_trunc_v8i8_to_v8i32(<8 x i8> %a0) {
+; CHECK-LABEL: @reduce_add_trunc_v8i8_to_v8i32(
+; CHECK-NEXT: [[TR:%.*]] = zext <8 x i8> [[A0:%.*]] to <8 x i32>
+; CHECK-NEXT: [[RED:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TR]])
+; CHECK-NEXT: ret i32 [[RED]]
+;
+ %tr = zext <8 x i8> %a0 to <8 x i32>
+ %red = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %tr)
+ ret i32 %red
+}
+
+
declare i32 @llvm.vector.reduce.add.v8i32(<8 x i32>)
declare i16 @llvm.vector.reduce.add.v8i16(<8 x i16>)
declare i8 @llvm.vector.reduce.add.v8i8(<8 x i8>)
diff --git a/llvm/test/Verifier/byval-size-limit.ll b/llvm/test/Verifier/byval-size-limit.ll
new file mode 100644
index 0000000..3eb462b
--- /dev/null
+++ b/llvm/test/Verifier/byval-size-limit.ll
@@ -0,0 +1,4 @@
+; RUN: not llvm-as < %s 2>&1 | FileCheck %s
+
+; CHECK: huge 'byval' arguments are unsupported
+define void @f(ptr byval([2147483648 x i16])) { ret void }
diff --git a/llvm/test/Verifier/param-align.ll b/llvm/test/Verifier/param-align.ll
index bfd01cb..caa8f9a 100644
--- a/llvm/test/Verifier/param-align.ll
+++ b/llvm/test/Verifier/param-align.ll
@@ -2,19 +2,19 @@
; Large vector for intrinsics is valid
; CHECK-NOT: llvm.fshr
-define dso_local <8192 x i32> @test_intrin(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt) {
+define dso_local <2147483648 x i32> @test_intrin(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt) {
entry:
- %b = call <8192 x i32> @llvm.fshr.v8192i32(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
- ret <8192 x i32> %b
+ %b = call <2147483648 x i32> @llvm.fshr.v8192i32(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
+ ret <2147483648 x i32> %b
}
-declare <8192 x i32> @llvm.fshr.v8192i32 (<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
+declare <2147483648 x i32> @llvm.fshr.v8192i32 (<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
; CHECK: Incorrect alignment of argument passed to called function!
; CHECK: bar
-define dso_local void @foo(<8192 x float> noundef %vec) {
+define dso_local void @foo(<2147483648 x float> noundef %vec) {
entry:
- call void @bar(<8192 x float> %vec)
+ call void @bar(<2147483648 x float> %vec)
ret void
}
-declare dso_local void @bar(<8192 x float>)
+declare dso_local void @bar(<2147483648 x float>)
diff --git a/llvm/test/Verifier/param-attr-align.ll b/llvm/test/Verifier/param-attr-align.ll
index 038bfa3..700efe5 100644
--- a/llvm/test/Verifier/param-attr-align.ll
+++ b/llvm/test/Verifier/param-attr-align.ll
@@ -1,9 +1,9 @@
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
-; CHECK: Attribute 'align' exceed the max size 2^14
+; CHECK: huge alignments are not supported yet
define dso_local void @foo(ptr %p) {
entry:
- call void @bar(ptr noundef byval(<8 x float>) align 32768 %p)
+ call void @bar(ptr noundef byval(<8 x float>) align 8589934592 %p)
ret void
}
diff --git a/llvm/test/Verifier/param-ret-align.ll b/llvm/test/Verifier/param-ret-align.ll
index dd302c3..98cbb4e 100644
--- a/llvm/test/Verifier/param-ret-align.ll
+++ b/llvm/test/Verifier/param-ret-align.ll
@@ -2,19 +2,19 @@
; Large vector for intrinsics is valid
; CHECK-NOT: llvm.fshr
-define dso_local <8192 x i32> @test_intrin(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt) {
+define dso_local <2147483648 x i32> @test_intrin(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt) {
entry:
- %b = call <8192 x i32> @llvm.fshr.v8192i32(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
- ret <8192 x i32> %b
+ %b = call <2147483648 x i32> @llvm.fshr.v8192i32(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
+ ret <2147483648 x i32> %b
}
-declare <8192 x i32> @llvm.fshr.v8192i32 (<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
+declare <2147483648 x i32> @llvm.fshr.v2147483648i32 (<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
; CHECK: Incorrect alignment of return type to called function!
; CHECK: bar
define dso_local void @foo() {
entry:
- call <8192 x float> @bar()
+ call <2147483648 x float> @bar()
ret void
}
-declare dso_local <8192 x float> @bar()
+declare dso_local <2147483648 x float> @bar()
diff --git a/llvm/unittests/ADT/SetOperationsTest.cpp b/llvm/unittests/ADT/SetOperationsTest.cpp
index b3d931c..da84c8a 100644
--- a/llvm/unittests/ADT/SetOperationsTest.cpp
+++ b/llvm/unittests/ADT/SetOperationsTest.cpp
@@ -8,6 +8,8 @@
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -16,6 +18,7 @@
using namespace llvm;
using testing::IsEmpty;
+using testing::UnorderedElementsAre;
namespace {
@@ -199,6 +202,38 @@ TEST(SetOperationsTest, SetSubtract) {
EXPECT_EQ(ExpectedSet2, Set2);
}
+TEST(SetOperationsTest, SetSubtractSmallPtrSet) {
+ int A[4];
+
+ // Set1.size() < Set2.size()
+ SmallPtrSet<int *, 4> Set1 = {&A[0], &A[1]};
+ SmallPtrSet<int *, 4> Set2 = {&A[1], &A[2], &A[3]};
+ set_subtract(Set1, Set2);
+ EXPECT_THAT(Set1, UnorderedElementsAre(&A[0]));
+
+ // Set1.size() > Set2.size()
+ Set1 = {&A[0], &A[1], &A[2]};
+ Set2 = {&A[0], &A[2]};
+ set_subtract(Set1, Set2);
+ EXPECT_THAT(Set1, UnorderedElementsAre(&A[1]));
+}
+
+TEST(SetOperationsTest, SetSubtractSmallVector) {
+ int A[4];
+
+ // Set1.size() < Set2.size()
+ SmallPtrSet<int *, 4> Set1 = {&A[0], &A[1]};
+ SmallVector<int *> Set2 = {&A[1], &A[2], &A[3]};
+ set_subtract(Set1, Set2);
+ EXPECT_THAT(Set1, UnorderedElementsAre(&A[0]));
+
+ // Set1.size() > Set2.size()
+ Set1 = {&A[0], &A[1], &A[2]};
+ Set2 = {&A[0], &A[2]};
+ set_subtract(Set1, Set2);
+ EXPECT_THAT(Set1, UnorderedElementsAre(&A[1]));
+}
+
TEST(SetOperationsTest, SetSubtractRemovedRemaining) {
std::set<int> Removed, Remaining;
diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp
index 4e5dccf..354cd18 100644
--- a/llvm/unittests/SandboxIR/TrackerTest.cpp
+++ b/llvm/unittests/SandboxIR/TrackerTest.cpp
@@ -198,3 +198,175 @@ define void @foo(i32 %v1) {
EXPECT_EQ(&*It++, Ret);
EXPECT_EQ(It, BB->end());
}
+
+// TODO: Test multi-instruction patterns.
+TEST_F(TrackerTest, RemoveFromParent) {
+ parseIR(C, R"IR(
+define i32 @foo(i32 %arg) {
+ %add0 = add i32 %arg, %arg
+ %add1 = add i32 %add0, %arg
+ ret i32 %add1
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+
+ auto *F = Ctx.createFunction(&LLVMF);
+ auto *Arg = F->getArg(0);
+ auto *BB = &*F->begin();
+ auto It = BB->begin();
+ sandboxir::Instruction *Add0 = &*It++;
+ sandboxir::Instruction *Add1 = &*It++;
+ sandboxir::Instruction *Ret = &*It++;
+
+ Ctx.save();
+ // Check removeFromParent().
+ Add1->removeFromParent();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+ // Removed instruction still be connected to operands and users.
+ EXPECT_EQ(Add1->getOperand(0), Add0);
+ EXPECT_EQ(Add1->getOperand(1), Arg);
+ EXPECT_EQ(Add0->getNumUses(), 1u);
+
+ // Check revert().
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+ EXPECT_EQ(Add1->getOperand(0), Add0);
+
+ // Same for the last instruction in the block.
+ Ctx.save();
+ Ret->removeFromParent();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(It, BB->end());
+ EXPECT_EQ(Ret->getOperand(0), Add1);
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+}
+
+// TODO: Test multi-instruction patterns.
+TEST_F(TrackerTest, MoveInstr) {
+ parseIR(C, R"IR(
+define i32 @foo(i32 %arg) {
+ %add0 = add i32 %arg, %arg
+ %add1 = add i32 %add0, %arg
+ ret i32 %add1
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+
+ auto *F = Ctx.createFunction(&LLVMF);
+ auto *BB = &*F->begin();
+ auto It = BB->begin();
+ sandboxir::Instruction *Add0 = &*It++;
+ sandboxir::Instruction *Add1 = &*It++;
+ sandboxir::Instruction *Ret = &*It++;
+
+ // Check moveBefore(Instruction *) with tracking enabled.
+ Ctx.save();
+ Add1->moveBefore(Add0);
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+ // Check revert().
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+
+ // Same for the last instruction in the block.
+ Ctx.save();
+ Ret->moveBefore(Add0);
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(It, BB->end());
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+
+ // Check moveBefore(BasicBlock &, BasicBlock::iterator) with tracking enabled.
+ Ctx.save();
+ Add1->moveBefore(*BB, Add0->getIterator());
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+ // Check revert().
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+
+ // Same for the last instruction in the block.
+ Ctx.save();
+ Ret->moveBefore(*BB, Add0->getIterator());
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(It, BB->end());
+ // Check revert().
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+
+ // Check moveAfter(Instruction *) with tracking enabled.
+ Ctx.save();
+ Add0->moveAfter(Add1);
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+ // Check revert().
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+
+ // Same for the last instruction in the block.
+ Ctx.save();
+ Ret->moveAfter(Add0);
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(It, BB->end());
+ // Check revert().
+ Ctx.revert();
+ It = BB->begin();
+ EXPECT_EQ(&*It++, Add0);
+ EXPECT_EQ(&*It++, Add1);
+ EXPECT_EQ(&*It++, Ret);
+ EXPECT_EQ(It, BB->end());
+}
diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
index 0349e63..27f29c3 100644
--- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
+++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
@@ -604,6 +604,8 @@ if (current_toolchain == default_toolchain) {
"__memory/concepts.h",
"__memory/construct_at.h",
"__memory/destruct_n.h",
+ "__memory/inout_ptr.h",
+ "__memory/out_ptr.h",
"__memory/pointer_traits.h",
"__memory/ranges_construct_at.h",
"__memory/ranges_uninitialized_algorithms.h",
diff --git a/llvm/utils/gn/secondary/lldb/source/API/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/API/BUILD.gn
index f0bf6a8..148f2cb 100644
--- a/llvm/utils/gn/secondary/lldb/source/API/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/source/API/BUILD.gn
@@ -86,6 +86,7 @@ target(liblldb_type, "liblldb") {
"SBQueue.cpp",
"SBQueueItem.cpp",
"SBReproducer.cpp",
+ "SBSaveCoreOptions.cpp",
"SBScriptObject.cpp",
"SBSection.cpp",
"SBSourceManager.cpp",
diff --git a/llvm/utils/gn/secondary/lldb/source/Symbol/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Symbol/BUILD.gn
index db769f2..3b1df82 100644
--- a/llvm/utils/gn/secondary/lldb/source/Symbol/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/source/Symbol/BUILD.gn
@@ -29,6 +29,7 @@ static_library("Symbol") {
"ObjectContainer.cpp",
"ObjectFile.cpp",
"PostfixExpression.cpp",
+ "SaveCoreOptions.cpp",
"Symbol.cpp",
"SymbolContext.cpp",
"SymbolFile.cpp",
diff --git a/llvm/utils/lit/lit/builtin_commands/cat.py b/llvm/utils/lit/lit/builtin_commands/cat.py
index 6fb2152..d6dbe88 100644
--- a/llvm/utils/lit/lit/builtin_commands/cat.py
+++ b/llvm/utils/lit/lit/builtin_commands/cat.py
@@ -10,7 +10,7 @@ except ImportError:
def convertToCaretAndMNotation(data):
newdata = StringIO()
if isinstance(data, str):
- data = bytearray(data)
+ data = bytearray(data.encode())
for intval in data:
if intval == 9 or intval == 10:
diff --git a/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp b/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp
index 5cac770..3a2042d 100644
--- a/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp
+++ b/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp
@@ -620,6 +620,7 @@ void allocateTilesToLiveRanges(
if (!activeRanges.remove(rangeToSpill)) {
bool removed = inactiveRanges.remove(rangeToSpill);
assert(removed && "expected a range to be removed!");
+ (void)removed;
}
}
rangeToSpill->tileId = tileAllocator.allocateInMemoryTileId();
diff --git a/utils/bazel/WORKSPACE b/utils/bazel/WORKSPACE
index 298b64f..7baca11 100644
--- a/utils/bazel/WORKSPACE
+++ b/utils/bazel/WORKSPACE
@@ -2,7 +2,6 @@
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
@@ -29,6 +28,14 @@ llvm_configure(name = "llvm-project")
maybe(
http_archive,
+ name = "rules_python",
+ sha256 = "778aaeab3e6cfd56d681c89f5c10d7ad6bf8d2f1a72de9de55b23081b2d31618",
+ strip_prefix = "rules_python-0.34.0",
+ url = "https://github.com/bazelbuild/rules_python/releases/download/0.34.0/rules_python-0.34.0.tar.gz",
+)
+
+maybe(
+ http_archive,
name = "llvm_zlib",
build_file = "@llvm-raw//utils/bazel/third_party_build:zlib-ng.BUILD",
sha256 = "e36bb346c00472a1f9ff2a0a4643e590a254be6379da7cddd9daeb9a7f296731",
@@ -76,10 +83,11 @@ apple_support_dependencies()
# Note: that building from source requires `m4` to be installed on the host machine.
# This is a known issue: https://github.com/bazelbuild/rules_foreign_cc/issues/755.
-git_repository(
+http_archive(
name = "rules_foreign_cc",
- remote = "https://github.com/bazelbuild/rules_foreign_cc.git",
- tag = "0.9.0",
+ sha256 = "4b33d62cf109bcccf286b30ed7121129cc34cf4f4ed9d8a11f38d9108f40ba74",
+ strip_prefix = "rules_foreign_cc-0.11.1",
+ url = "https://github.com/bazelbuild/rules_foreign_cc/releases/download/0.11.1/rules_foreign_cc-0.11.1.tar.gz",
)
load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")
@@ -112,11 +120,12 @@ maybe(
)
maybe(
- new_git_repository,
+ http_archive,
name = "pfm",
build_file = "@llvm-raw//utils/bazel/third_party_build:pfm.BUILD",
- remote = "https://git.code.sf.net/p/perfmon2/libpfm4",
- tag = "v4.12.1",
+ sha256 = "d18b97764c755528c1051d376e33545d0eb60c6ebf85680436813fa5b04cc3d1",
+ strip_prefix = "libpfm-4.13.0",
+ urls = ["https://versaweb.dl.sourceforge.net/project/perfmon2/libpfm4/libpfm-4.13.0.tar.gz"],
)
maybe(
@@ -129,3 +138,21 @@ maybe(
"https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.tar.gz",
],
)
+
+maybe(
+ http_archive,
+ name = "pybind11",
+ build_file = "@llvm-raw//utils/bazel/third_party_build:pybind.BUILD",
+ sha256 = "201966a61dc826f1b1879a24a3317a1ec9214a918c8eb035be2f30c3e9cfbdcb",
+ strip_prefix = "pybind11-2.10.3",
+ url = "https://github.com/pybind/pybind11/archive/v2.10.3.zip",
+)
+
+load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains")
+
+py_repositories()
+
+python_register_toolchains(
+ name = "python_3_12",
+ python_version = "3.12",
+)
diff --git a/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel b/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel
index cc57386..6d5a1b8 100644
--- a/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/lldb/BUILD.bazel
@@ -707,7 +707,9 @@ cc_library(
cc_library(
name = "Headers",
- hdrs = glob(["include/lldb/lldb-*.h"]),
+ hdrs = glob(["include/lldb/lldb-*.h"]) + [
+ "include/lldb/Symbol/SaveCoreOptions.h",
+ ],
strip_include_prefix = "include",
)
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index fe67286..0d0224e 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -918,24 +918,14 @@ exports_files(
glob(["lib/Bindings/Python/**/*.cpp"]),
)
-# In the targets related to Python bindings, the projects @pybind11 and
-# @local_config_python are defined by @pybind11_bazel. The latter contains
-# python headers, and can be configured in an out-of-tree bazel project via
-#
-# load("@pybind11_bazel//:python_configure.bzl", "python_configure")
-# python_configure(name = "local_config_python")
-#
-# For more up-to-date instructions, see
-# https://github.com/pybind/pybind11_bazel
-#
-# Some out-of-tree projects alias @python_runtime//:headers to
-# @local_config_python//:python_headers.
-
-MLIR_BINDINGS_PYTHON_HEADERS = [
- "lib/Bindings/Python/*.h",
- "include/mlir-c/Bindings/Python/*.h",
- "include/mlir/Bindings/Python/*.h",
-]
+filegroup(
+ name = "MLIRBindingsPythonHeaderFiles",
+ srcs = glob([
+ "lib/Bindings/Python/*.h",
+ "include/mlir-c/Bindings/Python/*.h",
+ "include/mlir/Bindings/Python/*.h",
+ ]),
+)
cc_library(
name = "MLIRBindingsPythonHeaders",
@@ -943,16 +933,12 @@ cc_library(
"include",
"lib/Bindings/Python",
],
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
- textual_hdrs = glob(MLIR_BINDINGS_PYTHON_HEADERS),
+ textual_hdrs = [":MLIRBindingsPythonHeaderFiles"],
deps = [
":CAPIIRHeaders",
":CAPITransformsHeaders",
- "@local_config_python//:python_headers",
"@pybind11",
+ "@rules_python//python/cc:current_py_cc_headers",
],
)
@@ -962,16 +948,12 @@ cc_library(
"include",
"lib/Bindings/Python",
],
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
- textual_hdrs = glob(MLIR_BINDINGS_PYTHON_HEADERS),
+ textual_hdrs = [":MLIRBindingsPythonHeaderFiles"],
deps = [
":CAPIIR",
":CAPITransforms",
- "@local_config_python//:python_headers",
"@pybind11",
+ "@rules_python//python/cc:current_py_cc_headers",
],
)
@@ -986,26 +968,25 @@ PYBIND11_FEATURES = [
"-use_header_modules",
]
-MLIR_PYTHON_BINDINGS_SOURCES = [
- "lib/Bindings/Python/IRAffine.cpp",
- "lib/Bindings/Python/IRAttributes.cpp",
- "lib/Bindings/Python/IRCore.cpp",
- "lib/Bindings/Python/IRInterfaces.cpp",
- "lib/Bindings/Python/IRModule.cpp",
- "lib/Bindings/Python/IRTypes.cpp",
- "lib/Bindings/Python/Pass.cpp",
- "lib/Bindings/Python/Rewrite.cpp",
-]
+filegroup(
+ name = "MLIRBindingsPythonSourceFiles",
+ srcs = [
+ "lib/Bindings/Python/IRAffine.cpp",
+ "lib/Bindings/Python/IRAttributes.cpp",
+ "lib/Bindings/Python/IRCore.cpp",
+ "lib/Bindings/Python/IRInterfaces.cpp",
+ "lib/Bindings/Python/IRModule.cpp",
+ "lib/Bindings/Python/IRTypes.cpp",
+ "lib/Bindings/Python/Pass.cpp",
+ "lib/Bindings/Python/Rewrite.cpp",
+ ],
+)
cc_library(
name = "MLIRBindingsPythonCore",
- srcs = MLIR_PYTHON_BINDINGS_SOURCES,
+ srcs = [":MLIRBindingsPythonSourceFiles"],
copts = PYBIND11_COPTS,
features = PYBIND11_FEATURES,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPIAsync",
":CAPIDebug",
@@ -1015,20 +996,16 @@ cc_library(
":Support",
":config",
"//llvm:Support",
- "@local_config_python//:python_headers",
"@pybind11",
+ "@rules_python//python/cc:current_py_cc_headers",
],
)
cc_library(
name = "MLIRBindingsPythonCoreNoCAPI",
- srcs = MLIR_PYTHON_BINDINGS_SOURCES,
+ srcs = [":MLIRBindingsPythonSourceFiles"],
copts = PYBIND11_COPTS,
features = PYBIND11_FEATURES,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPIAsyncHeaders",
":CAPIDebugHeaders",
@@ -1037,8 +1014,8 @@ cc_library(
":Support",
":config",
"//llvm:Support",
- "@local_config_python//:python_headers",
"@pybind11",
+ "@rules_python//python/cc:current_py_cc_headers",
],
)
@@ -1046,10 +1023,6 @@ cc_library(
# MLIRBindingsPythonCoreNoCAPI.
cc_library(
name = "MLIRBindingsPythonCAPIObjects",
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPIAsyncObjects",
":CAPIDebugObjects",
@@ -1068,10 +1041,6 @@ cc_binary(
features = PYBIND11_FEATURES,
linkshared = 1,
linkstatic = 0,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":MLIRBindingsPythonCore",
":MLIRBindingsPythonHeadersAndDeps",
@@ -1085,10 +1054,6 @@ cc_binary(
features = PYBIND11_FEATURES,
linkshared = 1,
linkstatic = 0,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPIIR",
":CAPILinalg",
@@ -1103,10 +1068,6 @@ cc_binary(
features = PYBIND11_FEATURES,
linkshared = 1,
linkstatic = 0,
- tags = [
- "manual", # External dependency
- "nobuildkite",
- ],
deps = [
":CAPIIR",
":CAPILLVM",
@@ -1122,10 +1083,6 @@ cc_binary(
features = PYBIND11_FEATURES,
linkshared = 1,
linkstatic = 0,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPIIR",
":CAPIQuant",
@@ -1141,10 +1098,6 @@ cc_binary(
features = PYBIND11_FEATURES,
linkshared = 1,
linkstatic = 0,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPIIR",
":CAPISparseTensor",
@@ -1161,15 +1114,11 @@ cc_binary(
features = PYBIND11_FEATURES,
linkshared = 1,
linkstatic = 0,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPIExecutionEngine",
":MLIRBindingsPythonHeadersAndDeps",
- "@local_config_python//:python_headers",
"@pybind11",
+ "@rules_python//python/cc:current_py_cc_headers",
],
)
@@ -1181,15 +1130,11 @@ cc_binary(
features = PYBIND11_FEATURES,
linkshared = 1,
linkstatic = 0,
- tags = [
- "manual", # External dependency
- "nobuildkite", # TODO(gcmn): Add support for this target
- ],
deps = [
":CAPILinalg",
":MLIRBindingsPythonHeadersAndDeps",
- "@local_config_python//:python_headers",
"@pybind11",
+ "@rules_python//python/cc:current_py_cc_headers",
],
)
diff --git a/utils/bazel/third_party_build/pybind.BUILD b/utils/bazel/third_party_build/pybind.BUILD
new file mode 100644
index 0000000..d9fb431
--- /dev/null
+++ b/utils/bazel/third_party_build/pybind.BUILD
@@ -0,0 +1,15 @@
+cc_library(
+ name = "pybind11",
+ hdrs = glob(
+ include = ["include/pybind11/**/*.h"],
+ exclude = [
+ # Deprecated file that just emits a warning
+ "include/pybind11/common.h",
+ ],
+ ),
+ includes = ["include"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@rules_python//python/cc:current_py_cc_headers",
+ ],
+)