14 changes: 7 additions & 7 deletions compiler-rt/lib/orc/macho_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class MachOPlatformRuntimeState {

const char *dlerror();
void *dlopen(std::string_view Name, int Mode);
int dlupdate(void *DSOHandle, int Mode);
int dlupdate(void *DSOHandle);
int dlclose(void *DSOHandle);
void *dlsym(void *DSOHandle, const char *Symbol);

Expand Down Expand Up @@ -295,7 +295,7 @@ class MachOPlatformRuntimeState {
Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock,
JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);

Error dlupdateImpl(void *DSOHandle, int Mode);
Error dlupdateImpl(void *DSOHandle);
Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock,
JITDylibState &JDS);
Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock,
Expand Down Expand Up @@ -710,13 +710,13 @@ void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {
}
}

int MachOPlatformRuntimeState::dlupdate(void *DSOHandle, int Mode) {
int MachOPlatformRuntimeState::dlupdate(void *DSOHandle) {
ORC_RT_DEBUG({
std::string S;
printdbg("MachOPlatform::dlupdate(%p) (%s)\n", DSOHandle, S.c_str());
});
std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex);
if (auto Err = dlupdateImpl(DSOHandle, Mode)) {
if (auto Err = dlupdateImpl(DSOHandle)) {
// FIXME: Make dlerror thread safe.
DLFcnError = toString(std::move(Err));
return -1;
Expand Down Expand Up @@ -1179,7 +1179,7 @@ Error MachOPlatformRuntimeState::dlopenInitialize(
return Error::success();
}

Error MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle, int Mode) {
Error MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle) {
std::unique_lock<std::mutex> Lock(JDStatesMutex);

// Try to find JITDylib state by DSOHandle.
Expand Down Expand Up @@ -1513,8 +1513,8 @@ void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
return MachOPlatformRuntimeState::get().dlopen(path, mode);
}

int __orc_rt_macho_jit_dlupdate(void *dso_handle, int mode) {
return MachOPlatformRuntimeState::get().dlupdate(dso_handle, mode);
int __orc_rt_macho_jit_dlupdate(void *dso_handle) {
return MachOPlatformRuntimeState::get().dlupdate(dso_handle);
}

int __orc_rt_macho_jit_dlclose(void *dso_handle) {
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/lib/orc/macho_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ ORC_RT_INTERFACE void __orc_rt_macho_cxa_finalize(void *dso_handle);
// dlfcn functions.
ORC_RT_INTERFACE const char *__orc_rt_macho_jit_dlerror();
ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlopen(const char *path, int mode);
ORC_RT_INTERFACE int __orc_rt_macho_jit_dlupdate(void *dso_handle, int mode);
ORC_RT_INTERFACE int __orc_rt_macho_jit_dlupdate(void *dso_handle);
ORC_RT_INTERFACE int __orc_rt_macho_jit_dlclose(void *dso_handle);
ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlsym(void *dso_handle,
const char *symbol);
Expand Down
3 changes: 3 additions & 0 deletions compiler-rt/lib/rtsan/rtsan_assertions.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ void ExpectNotRealtime(Context &context, const DiagnosticsInfo &info,
if (context.InRealtimeContext() && !context.IsBypassed()) {
ScopedBypass sb{context};

if (IsFunctionSuppressed(info.func_name))
return;

__sanitizer::BufferedStackTrace stack;

// We use the unwind_on_fatal flag here because of precedent with other
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/rtsan/rtsan_checks.inc
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
// SummaryKind should be a string literal.

RTSAN_CHECK(CallStackContains, "call-stack-contains")
RTSAN_CHECK(FunctionNameMatches, "function-name-matches")
13 changes: 13 additions & 0 deletions compiler-rt/lib/rtsan/rtsan_suppressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,16 @@ bool __rtsan::IsStackTraceSuppressed(const StackTrace &stack) {
}
return false;
}

bool __rtsan::IsFunctionSuppressed(const char *function_name) {
if (suppression_ctx == nullptr)
return false;

const char *flag_name = ConvertTypeToFlagName(ErrorType::FunctionNameMatches);

if (!suppression_ctx->HasSuppressionType(flag_name))
return false;

Suppression *s;
return suppression_ctx->Match(function_name, flag_name, &s);
}
1 change: 1 addition & 0 deletions compiler-rt/lib/rtsan/rtsan_suppressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ namespace __rtsan {

void InitializeSuppressions();
bool IsStackTraceSuppressed(const __sanitizer::StackTrace &stack);
bool IsFunctionSuppressed(const char *function_name);

} // namespace __rtsan
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ TEST(SanitizerCommon, IsAccessibleMemoryRange) {
EXPECT_TRUE(IsAccessibleMemoryRange(mem + 2 * page_size, page_size));
EXPECT_FALSE(IsAccessibleMemoryRange(mem, 3 * page_size));
EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2));

munmap((void *)mem, 3 * page_size);
}

} // namespace __sanitizer
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/Posix/instrprof-visibility.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// XFAIL: target={{.*}}-aix{{.*}}
// RUN: %clangxx_profgen -fcoverage-mapping %S/Inputs/instrprof-visibility-helper.cpp -o %t %s
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata merge %t.profraw -o %t.profdata
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/coverage-inline.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// XFAIL: target={{.*}}-aix{{.*}}
// Test that the instrumentation puts the right linkage on the profile data for
// inline functions.
// RUN: %clang_profgen -g -fcoverage-mapping -c -o %t1.o %s -DOBJECT_1
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/coverage_comments.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// XFAIL: target={{.*}}-aix{{.*}}
// RUN: %clangxx_profgen -fcoverage-mapping -Wno-comment -o %t %s
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/coverage_emptylines.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// XFAIL: target={{.*}}-aix{{.*}}
// Remove comments first.
// RUN: sed 's/[ \t]*\/\/.*//' %s > %t.stripped.cpp
// RUN: %clangxx_profgen -fcoverage-mapping -o %t %t.stripped.cpp
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/instrprof-merging.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// UNSUPPORTED: target={{.*windows.*}}
// XFAIL: target={{.*}}-aix{{.*}}
// 1) Compile shared code into different object files and into an executable.

// RUN: %clangxx_profgen -std=c++14 -fcoverage-mapping %s -c -o %t.v1.o \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int main(int argc, const char *argv[]) {

return 0;
}
// XFAIL: target={{.*}}-aix{{.*}}
// CHECK: 10| |#include <stdio.h>
// CHECK: 11| |
// CHECK: 12| |extern void __llvm_profile_set_file_object(FILE *, int);
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/instrprof-set-file-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ int main(int argc, const char *argv[]) {
__llvm_profile_set_file_object(F, 0);
return 0;
}
// XFAIL: target={{.*}}-aix{{.*}}
// CHECK: 8| |#include <stdio.h>
// CHECK: 9| |
// CHECK: 10| |extern void __llvm_profile_set_file_object(FILE *, int);
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/instrprof-without-libc.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// XFAIL: target={{.*}}-aix{{.*}}
// RUN: %clang_profgen -DCHECK_SYMBOLS -O3 -o %t.symbols %s
// RUN: llvm-nm %t.symbols | FileCheck %s --check-prefix=CHECK-SYMBOLS
// RUN: %clang_profgen -O3 -o %t %s
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/test/profile/instrprof-write-file-only.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// XFAIL: target={{.*}}-aix{{.*}}
// RUN: %clang_profgen -o %t -O3 %s
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
Expand Down
8 changes: 2 additions & 6 deletions compiler-rt/test/profile/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,8 @@ def exclude_unsupported_files_for_aix(dirname):
f = open(source_path, "r")
try:
data = f.read()
# -fprofile-instr-generate and rpath are not supported on AIX, exclude all tests with them.
if (
"%clang_profgen" in data
or "%clangxx_profgen" in data
or "-rpath" in data
):
# rpath is not supported on AIX, exclude all tests with them.
if ( "-rpath" in data ):
config.excludes += [filename]
finally:
f.close()
Expand Down
25 changes: 20 additions & 5 deletions compiler-rt/test/rtsan/stack_suppressions.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clangxx -fsanitize=realtime %s -o %t
// RUN: %env_rtsan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOSUPPRESSIONS
// RUN: %env_rtsan_opts=suppressions='%s.supp' not %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: ios

Expand All @@ -8,8 +9,11 @@
#include <stdlib.h>
#include <unistd.h>

#include <atomic>
#include <vector>

std::atomic<int> cas_atomic{0};

void *MallocViolation() { return malloc(10); }

void VectorViolations() {
Expand All @@ -22,13 +26,18 @@ void VectorViolations() {
v.reserve(10);
}

void BlockFunc() [[clang::blocking]] { usleep(1); }
void BlockFunc() [[clang::blocking]] {
int expected = 0;
while (!cas_atomic.compare_exchange_weak(expected, 1)) {
expected = cas_atomic.load();
}
}

void *process() [[clang::nonblocking]] {
void *ptr = MallocViolation();
VectorViolations();
BlockFunc();
free(ptr);
void *ptr = MallocViolation(); // Suppressed call-stack-contains
VectorViolations(); // Suppressed call-stack-contains with regex
BlockFunc(); // Suppressed function-name-matches
free(ptr); // Suppressed function-name-matches

// This is the one that should abort the program
// Everything else is suppressed
Expand All @@ -51,3 +60,9 @@ int main() {
// CHECK-NOT: vector
// CHECK-NOT: free
// CHECK-NOT: BlockFunc

// CHECK-NOSUPPRESSIONS: malloc
// CHECK-NOSUPPRESSIONS: vector
// CHECK-NOSUPPRESSIONS: free
// CHECK-NOSUPPRESSIONS: BlockFunc
// CHECK-NOSUPPRESSIONS: usleep
5 changes: 3 additions & 2 deletions compiler-rt/test/rtsan/stack_suppressions.cpp.supp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
call-stack-contains:MallocViolation
call-stack-contains:std::*vector
call-stack-contains:free
call-stack-contains:BlockFunc

function-name-matches:free
function-name-matches:Block*
2 changes: 1 addition & 1 deletion flang/lib/Evaluate/intrinsics-library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ template <> struct HostRuntimeLibrary<double, LibraryVersion::LibmExtensions> {
static_assert(map.Verify(), "map must be sorted");
};

#if HAS_FLOAT80 || HAS_LDBL128
#if defined(__GLIBC__) && (HAS_FLOAT80 || HAS_LDBL128)
template <>
struct HostRuntimeLibrary<long double, LibraryVersion::LibmExtensions> {
using F = FuncPointer<long double, long double>;
Expand Down
16 changes: 12 additions & 4 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2070,7 +2070,9 @@ static void genStandaloneSimd(lower::AbstractConverter &converter,
loopNestClauseOps, iv);

EntryBlockArgs simdArgs;
// TODO: Add private, reduction syms and vars.
// TODO: Add private syms and vars.
simdArgs.reduction.syms = simdReductionSyms;
simdArgs.reduction.vars = simdClauseOps.reductionVars;
auto simdOp =
genWrapperOp<mlir::omp::SimdOp>(converter, loc, simdClauseOps, simdArgs);

Expand Down Expand Up @@ -2228,7 +2230,9 @@ static void genCompositeDistributeParallelDoSimd(
wsloopOp.setComposite(/*val=*/true);

EntryBlockArgs simdArgs;
// TODO: Add private, reduction syms and vars.
// TODO: Add private syms and vars.
simdArgs.reduction.syms = simdReductionSyms;
simdArgs.reduction.vars = simdClauseOps.reductionVars;
auto simdOp =
genWrapperOp<mlir::omp::SimdOp>(converter, loc, simdClauseOps, simdArgs);
simdOp.setComposite(/*val=*/true);
Expand Down Expand Up @@ -2285,7 +2289,9 @@ static void genCompositeDistributeSimd(lower::AbstractConverter &converter,
distributeOp.setComposite(/*val=*/true);

EntryBlockArgs simdArgs;
// TODO: Add private, reduction syms and vars.
// TODO: Add private syms and vars.
simdArgs.reduction.syms = simdReductionSyms;
simdArgs.reduction.vars = simdClauseOps.reductionVars;
auto simdOp =
genWrapperOp<mlir::omp::SimdOp>(converter, loc, simdClauseOps, simdArgs);
simdOp.setComposite(/*val=*/true);
Expand Down Expand Up @@ -2342,7 +2348,9 @@ static void genCompositeDoSimd(lower::AbstractConverter &converter,
wsloopOp.setComposite(/*val=*/true);

EntryBlockArgs simdArgs;
// TODO: Add private, reduction syms and vars.
// TODO: Add private syms and vars.
simdArgs.reduction.syms = simdReductionSyms;
simdArgs.reduction.vars = simdClauseOps.reductionVars;
auto simdOp =
genWrapperOp<mlir::omp::SimdOp>(converter, loc, simdClauseOps, simdArgs);
simdOp.setComposite(/*val=*/true);
Expand Down
9 changes: 6 additions & 3 deletions flang/runtime/Float128Math/math-entries.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,6 @@ DEFINE_SIMPLE_ALIAS(Hypot, std::hypot)
DEFINE_SIMPLE_ALIAS(Ilogb, std::ilogb)
DEFINE_SIMPLE_ALIAS(Isinf, std::isinf)
DEFINE_SIMPLE_ALIAS(Isnan, std::isnan)
DEFINE_SIMPLE_ALIAS(J0, j0l)
DEFINE_SIMPLE_ALIAS(J1, j1l)
DEFINE_SIMPLE_ALIAS(Jn, jnl)
DEFINE_SIMPLE_ALIAS(Ldexp, std::ldexp)
DEFINE_SIMPLE_ALIAS(Lgamma, std::lgamma)
DEFINE_SIMPLE_ALIAS(Llround, std::llround)
Expand All @@ -207,9 +204,15 @@ DEFINE_SIMPLE_ALIAS(Tan, std::tan)
DEFINE_SIMPLE_ALIAS(Tanh, std::tanh)
DEFINE_SIMPLE_ALIAS(Tgamma, std::tgamma)
DEFINE_SIMPLE_ALIAS(Trunc, std::trunc)

#if defined(__GLIBC__) && defined(_GNU_SOURCE)
DEFINE_SIMPLE_ALIAS(J0, j0l)
DEFINE_SIMPLE_ALIAS(J1, j1l)
DEFINE_SIMPLE_ALIAS(Jn, jnl)
DEFINE_SIMPLE_ALIAS(Y0, y0l)
DEFINE_SIMPLE_ALIAS(Y1, y1l)
DEFINE_SIMPLE_ALIAS(Yn, ynl)
#endif

// Use numeric_limits to produce infinity of the right type.
#define F128_RT_INFINITY \
Expand Down
5 changes: 5 additions & 0 deletions flang/test/Driver/atomic.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
!RUN: %flang --target=aarch64-unknown-linux-gnu -fuse-ld=ld -fopenmp -rtlib=libgcc -### %s 2>&1 | FileCheck --check-prefixes=GCC %s
!RUN: %flang --target=aarch64-unknown-linux-gnu -fuse-ld=ld -fopenmp -rtlib=compiler-rt -### %s 2>&1 | FileCheck --check-prefixes=CRT %s

!GCC: -latomic
!CRT-NOT: -latomic
262 changes: 262 additions & 0 deletions flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
! RUN: %flang_fc1 -fopenmp -emit-llvm %s -o - | FileCheck %s

! Combinational testing of control flow graph and builder insertion points
! in mlir-to-llvm conversion:
! - mixing multiple delayed privatizations and multiple reductions
! - multiple blocks in the private alloc region
! - private alloc region has to read from the mold variable
! - firstprivate
! - multiple blocks in the private copy region
! - multiple blocks in the reduction init region
! - reduction init region has to read from the mold variable
! - re-used omp.private ops
! - re-used omp.reduction.declare ops
! - unstructured code inside of the parallel region
! - needs private dealloc region, and this has multiple blocks
! - needs reduction cleanup region, and this has multiple blocks

! This maybe belongs in the mlir tests, but what we are doing here is complex
! enough that I find the kind of minimised mlir code preferred by mlir reviewers
! hard to read without some fortran here for reference. Nothing like this would
! be generated by other upstream users of the MLIR OpenMP dialect.

subroutine worst_case(a, b, c, d)
real, allocatable :: a(:), b(:), c(:), d(:)
integer i

!$omp parallel firstprivate(a,b) reduction(+:c,d)
if (sum(a) == 1) stop 1
!$omp end parallel
end subroutine

! CHECK-LABEL: define internal void @worst_case_..omp_par
! CHECK-NEXT: omp.par.entry:
! [reduction alloc regions inlined here]
! CHECK: br label %omp.private.latealloc

! CHECK: omp.private.latealloc: ; preds = %omp.par.entry
! CHECK-NEXT: br label %omp.private.alloc5

! CHECK: omp.private.alloc5: ; preds = %omp.private.latealloc
! [begin private alloc for first var]
! [read the length from the mold argument]
! [if it is non-zero...]
! CHECK: br i1 {{.*}}, label %omp.private.alloc6, label %omp.private.alloc7

! CHECK: omp.private.alloc7: ; preds = %omp.private.alloc5
! [finish private alloc for first var with zero extent]
! CHECK: br label %omp.private.alloc8

! CHECK: omp.private.alloc8: ; preds = %omp.private.alloc6, %omp.private.alloc7
! CHECK-NEXT: br label %omp.region.cont4

! CHECK: omp.region.cont4: ; preds = %omp.private.alloc8
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.private.alloc

! CHECK: omp.private.alloc: ; preds = %omp.region.cont4
! [begin private alloc for first var]
! [read the length from the mold argument]
! [if it is non-zero...]
! CHECK: br i1 %{{.*}}, label %omp.private.alloc1, label %omp.private.alloc2

! CHECK: omp.private.alloc2: ; preds = %omp.private.alloc
! [finish private alloc for second var with zero extent]
! CHECK: br label %omp.private.alloc3

! CHECK: omp.private.alloc3: ; preds = %omp.private.alloc1, %omp.private.alloc2
! CHECK-NEXT: br label %omp.region.cont

! CHECK: omp.region.cont: ; preds = %omp.private.alloc3
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.private.copy

! CHECK: omp.private.copy: ; preds = %omp.region.cont
! CHECK-NEXT: br label %omp.private.copy10

! CHECK: omp.private.copy10: ; preds = %omp.private.copy
! [begin firstprivate copy for first var]
! [read the length, is it non-zero?]
! CHECK: br i1 %{{.*}}, label %omp.private.copy11, label %omp.private.copy12

! CHECK: omp.private.copy12: ; preds = %omp.private.copy11, %omp.private.copy10
! CHECK-NEXT: br label %omp.region.cont9

! CHECK: omp.region.cont9: ; preds = %omp.private.copy12
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.private.copy14

! CHECK: omp.private.copy14: ; preds = %omp.region.cont9
! [begin firstprivate copy for second var]
! [read the length, is it non-zero?]
! CHECK: br i1 %{{.*}}, label %omp.private.copy15, label %omp.private.copy16

! CHECK: omp.private.copy16: ; preds = %omp.private.copy15, %omp.private.copy14
! CHECK-NEXT: br label %omp.region.cont13

! CHECK: omp.region.cont13: ; preds = %omp.private.copy16
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.reduction.init

! CHECK: omp.reduction.init: ; preds = %omp.region.cont13
! [deffered stores for results of reduction alloc regions]
! CHECK: br label %[[VAL_96:.*]]

! CHECK: omp.reduction.neutral: ; preds = %omp.reduction.init
! [start of reduction initialization region]
! [null check:]
! CHECK: br i1 %{{.*}}, label %omp.reduction.neutral18, label %omp.reduction.neutral19

! CHECK: omp.reduction.neutral19: ; preds = %omp.reduction.neutral
! [malloc and assign the default value to the reduction variable]
! CHECK: br label %omp.reduction.neutral20

! CHECK: omp.reduction.neutral20: ; preds = %omp.reduction.neutral18, %omp.reduction.neutral19
! CHECK-NEXT: br label %omp.region.cont17

! CHECK: omp.region.cont17: ; preds = %omp.reduction.neutral20
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.reduction.neutral22

! CHECK: omp.reduction.neutral22: ; preds = %omp.region.cont17
! [start of reduction initialization region]
! [null check:]
! CHECK: br i1 %{{.*}}, label %omp.reduction.neutral23, label %omp.reduction.neutral24

! CHECK: omp.reduction.neutral24: ; preds = %omp.reduction.neutral22
! [malloc and assign the default value to the reduction variable]
! CHECK: br label %omp.reduction.neutral25

! CHECK: omp.reduction.neutral25: ; preds = %omp.reduction.neutral23, %omp.reduction.neutral24
! CHECK-NEXT: br label %omp.region.cont21

! CHECK: omp.region.cont21: ; preds = %omp.reduction.neutral25
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.par.region

! CHECK: omp.par.region: ; preds = %omp.region.cont21
! CHECK-NEXT: br label %omp.par.region27

! CHECK: omp.par.region27: ; preds = %omp.par.region
! [call SUM runtime function]
! [if (sum(a) == 1)]
! CHECK: br i1 %{{.*}}, label %omp.par.region28, label %omp.par.region29

! CHECK: omp.par.region29: ; preds = %omp.par.region27
! CHECK-NEXT: br label %omp.region.cont26

! CHECK: omp.region.cont26: ; preds = %omp.par.region28, %omp.par.region29
! [omp parallel region done, call into the runtime to complete reduction]
! CHECK: %[[VAL_233:.*]] = call i32 @__kmpc_reduce(
! CHECK: switch i32 %[[VAL_233]], label %reduce.finalize [
! CHECK-NEXT: i32 1, label %reduce.switch.nonatomic
! CHECK-NEXT: i32 2, label %reduce.switch.atomic
! CHECK-NEXT: ]

! CHECK: reduce.switch.atomic: ; preds = %omp.region.cont26
! CHECK-NEXT: unreachable

! CHECK: reduce.switch.nonatomic: ; preds = %omp.region.cont26
! CHECK-NEXT: %[[red_private_value_0:.*]] = load ptr, ptr %{{.*}}, align 8
! CHECK-NEXT: br label %omp.reduction.nonatomic.body

! [various blocks implementing the reduction]

! CHECK: omp.region.cont35: ; preds =
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: call void @__kmpc_end_reduce(
! CHECK-NEXT: br label %reduce.finalize

! CHECK: reduce.finalize: ; preds =
! CHECK-NEXT: br label %omp.par.pre_finalize

! CHECK: omp.par.pre_finalize: ; preds = %reduce.finalize
! CHECK-NEXT: %{{.*}} = load ptr, ptr
! CHECK-NEXT: br label %omp.reduction.cleanup

! CHECK: omp.reduction.cleanup: ; preds = %omp.par.pre_finalize
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.reduction.cleanup41, label %omp.reduction.cleanup42

! CHECK: omp.reduction.cleanup42: ; preds = %omp.reduction.cleanup41, %omp.reduction.cleanup
! CHECK-NEXT: br label %omp.region.cont40

! CHECK: omp.region.cont40: ; preds = %omp.reduction.cleanup42
! CHECK-NEXT: %{{.*}} = load ptr, ptr
! CHECK-NEXT: br label %omp.reduction.cleanup44

! CHECK: omp.reduction.cleanup44: ; preds = %omp.region.cont40
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.reduction.cleanup45, label %omp.reduction.cleanup46

! CHECK: omp.reduction.cleanup46: ; preds = %omp.reduction.cleanup45, %omp.reduction.cleanup44
! CHECK-NEXT: br label %omp.region.cont43

! CHECK: omp.region.cont43: ; preds = %omp.reduction.cleanup46
! CHECK-NEXT: br label %omp.private.dealloc

! CHECK: omp.private.dealloc: ; preds = %omp.region.cont43
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.private.dealloc48, label %omp.private.dealloc49

! CHECK: omp.private.dealloc49: ; preds = %omp.private.dealloc48, %omp.private.dealloc
! CHECK-NEXT: br label %omp.region.cont47

! CHECK: omp.region.cont47: ; preds = %omp.private.dealloc49
! CHECK-NEXT: br label %omp.private.dealloc51

! CHECK: omp.private.dealloc51: ; preds = %omp.region.cont47
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.private.dealloc52, label %omp.private.dealloc53

! CHECK: omp.private.dealloc53: ; preds = %omp.private.dealloc52, %omp.private.dealloc51
! CHECK-NEXT: br label %omp.region.cont50

! CHECK: omp.region.cont50: ; preds = %omp.private.dealloc53
! CHECK-NEXT: br label %omp.par.outlined.exit.exitStub

! CHECK: omp.private.dealloc52: ; preds = %omp.private.dealloc51
! [dealloc memory]
! CHECK: br label %omp.private.dealloc53

! CHECK: omp.private.dealloc48: ; preds = %omp.private.dealloc
! [dealloc memory]
! CHECK: br label %omp.private.dealloc49

! CHECK: omp.reduction.cleanup45: ; preds = %omp.reduction.cleanup44
! CHECK-NEXT: call void @free(
! CHECK-NEXT: br label %omp.reduction.cleanup46

! CHECK: omp.reduction.cleanup41: ; preds = %omp.reduction.cleanup
! CHECK-NEXT: call void @free(
! CHECK-NEXT: br label %omp.reduction.cleanup42

! CHECK: omp.par.region28: ; preds = %omp.par.region27
! CHECK-NEXT: call {} @_FortranAStopStatement

! CHECK: omp.reduction.neutral23: ; preds = %omp.reduction.neutral22
! [source length was zero: finish initializing array]
! CHECK: br label %omp.reduction.neutral25

! CHECK: omp.reduction.neutral18: ; preds = %omp.reduction.neutral
! [source length was zero: finish initializing array]
! CHECK: br label %omp.reduction.neutral20

! CHECK: omp.private.copy15: ; preds = %omp.private.copy14
! [source length was non-zero: call assign runtime]
! CHECK: br label %omp.private.copy16

! CHECK: omp.private.copy11: ; preds = %omp.private.copy10
! [source length was non-zero: call assign runtime]
! CHECK: br label %omp.private.copy12

! CHECK: omp.private.alloc1: ; preds = %omp.private.alloc
! [var extent was non-zero: malloc a private array]
! CHECK: br label %omp.private.alloc3

! CHECK: omp.private.alloc6: ; preds = %omp.private.alloc5
! [var extent was non-zero: malloc a private array]
! CHECK: br label %omp.private.alloc8

! CHECK: omp.par.outlined.exit.exitStub: ; preds = %omp.region.cont50
! CHECK-NEXT: ret void
46 changes: 46 additions & 0 deletions flang/test/Integration/OpenMP/private-global.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
!RUN: %flang_fc1 -emit-llvm -fopenmp %s -o - | FileCheck %s

! Regression test for https://github.com/llvm/llvm-project/issues/106297

program bug
implicit none
integer :: table(10)
!$OMP PARALLEL PRIVATE(table)
table = 50
if (any(table/=50)) then
stop 'fail 3'
end if
!$OMP END PARALLEL
print *,'ok'
End Program


! CHECK-LABEL: define internal void {{.*}}..omp_par(
! CHECK: omp.par.entry:
! CHECK: %[[VAL_9:.*]] = alloca i32, align 4
! CHECK: %[[VAL_10:.*]] = load i32, ptr %[[VAL_11:.*]], align 4
! CHECK: store i32 %[[VAL_10]], ptr %[[VAL_9]], align 4
! CHECK: %[[VAL_12:.*]] = load i32, ptr %[[VAL_9]], align 4
! CHECK: %[[PRIV_TABLE:.*]] = alloca [10 x i32], i64 1, align 4
! ...
! check that we use the private copy of table for the assignment
! CHECK: omp.par.region1:
! CHECK: %[[ELEMENTAL_TMP:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8
! CHECK: %[[TABLE_BOX_ADDR:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8
! CHECK: %[[BOXED_FIFTY:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8
! CHECK: %[[TABLE_BOX_ADDR2:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i64 1, align 8
! CHECK: %[[TABLE_BOX_VAL:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr undef, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20240719, i8 1, i8 9, i8 0, i8 0, [1 x [3 x i64]] {{\[\[}}3 x i64] [i64 1, i64 10, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64)]] }, ptr %[[PRIV_TABLE]], 0
! CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[TABLE_BOX_VAL]], ptr %[[TABLE_BOX_ADDR]], align 8
! CHECK: %[[TABLE_BOX_VAL2:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[TABLE_BOX_ADDR]], align 8
! CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[TABLE_BOX_VAL2]], ptr %[[TABLE_BOX_ADDR2]], align 8
! CHECK: %[[VAL_26:.*]] = call {} @_FortranAAssign(ptr %[[TABLE_BOX_ADDR2]], ptr %[[BOXED_FIFTY]], ptr @{{.*}}, i32 9)
! ...
! check that we use the private copy of table for table/=50
! CHECK: omp.par.region3:
! CHECK: %[[VAL_44:.*]] = sub nsw i64 %{{.*}}, 1
! CHECK: %[[VAL_45:.*]] = mul nsw i64 %[[VAL_44]], 1
! CHECK: %[[VAL_46:.*]] = mul nsw i64 %[[VAL_45]], 1
! CHECK: %[[VAL_47:.*]] = add nsw i64 %[[VAL_46]], 0
! CHECK: %[[VAL_48:.*]] = getelementptr i32, ptr %[[PRIV_TABLE]], i64 %[[VAL_47]]
! CHECK: %[[VAL_49:.*]] = load i32, ptr %[[VAL_48]], align 4
! CHECK: %[[VAL_50:.*]] = icmp ne i32 %[[VAL_49]], 50
24 changes: 24 additions & 0 deletions flang/test/Lower/OpenMP/simd.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
! RUN: %flang_fc1 -flang-experimental-hlfir -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s
! RUN: bbc -hlfir -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s

!CHECK: omp.declare_reduction @[[REDUCER:.*]] : i32

!CHECK-LABEL: func @_QPsimd()
subroutine simd
integer :: i
Expand Down Expand Up @@ -273,3 +275,25 @@ subroutine lastprivate_with_simd
sum = i + 1
end do
end subroutine

!CHECK-LABEL: func @_QPsimd_with_reduction_clause()
subroutine simd_with_reduction_clause
integer :: i, x
x = 0
! CHECK: %[[LB:.*]] = arith.constant 1 : i32
! CHECK-NEXT: %[[UB:.*]] = arith.constant 9 : i32
! CHECK-NEXT: %[[STEP:.*]] = arith.constant 1 : i32
! CHECK-NEXT: omp.simd reduction(@[[REDUCER]] %[[X:.*]]#0 -> %[[X_RED:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[I:.*]]) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) {
!$omp simd reduction(+:x)
do i=1, 9
! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_RED]] {uniq_name = "_QFsimd_with_reduction_clauseEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.store %[[I]] to %[[LOCAL:.*]]#1 : !fir.ref<i32>
! CHECK: %[[X_LD:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32>
! CHECK: %[[I_LD:.*]] = fir.load %[[LOCAL]]#0 : !fir.ref<i32>
! CHECK: %[[SUM:.*]] = arith.addi %[[X_LD]], %[[I_LD]] : i32
! CHECK: hlfir.assign %[[SUM]] to %[[X_DECL]]#0 : i32, !fir.ref<i32>
x = x+i
end do
!$OMP end simd
end subroutine
1 change: 1 addition & 0 deletions libc/config/gpu/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.ceilf16
libc.src.math.copysignf16
libc.src.math.exp10f16
libc.src.math.exp10m1f16
libc.src.math.exp2f16
libc.src.math.expf16
libc.src.math.f16add
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.ceilf16
libc.src.math.copysignf16
libc.src.math.exp10f16
libc.src.math.exp10m1f16
libc.src.math.exp2f16
libc.src.math.exp2m1f16
libc.src.math.expf16
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| exp10 | |check| | |check| | | |check| | | 7.12.6.2 | F.10.3.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| exp10m1 | | | | | | 7.12.6.3 | F.10.3.3 |
| exp10m1 | | | | |check| | | 7.12.6.3 | F.10.3.3 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| exp2 | |check| | |check| | | |check| | | 7.12.6.4 | F.10.3.4 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
Expand Down
2 changes: 2 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"exp10f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
GuardedFunctionSpec<"exp10f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,

GuardedFunctionSpec<"exp10m1f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,

FunctionSpec<"remainder", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"remainderf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"remainderl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
Expand Down
2 changes: 2 additions & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ add_math_entrypoint_object(exp10)
add_math_entrypoint_object(exp10f)
add_math_entrypoint_object(exp10f16)

add_math_entrypoint_object(exp10m1f16)

add_math_entrypoint_object(expm1)
add_math_entrypoint_object(expm1f)
add_math_entrypoint_object(expm1f16)
Expand Down
21 changes: 21 additions & 0 deletions libc/src/math/exp10m1f16.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for exp10m1f16 --------------------*- 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 LLVM_LIBC_SRC_MATH_EXP10M1F16_H
#define LLVM_LIBC_SRC_MATH_EXP10M1F16_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float16 exp10m1f16(float16 x);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_EXP10M1F16_H
23 changes: 23 additions & 0 deletions libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,29 @@ add_entrypoint_object(
-O3
)

add_entrypoint_object(
exp10m1f16
SRCS
exp10m1f16.cpp
HDRS
../exp10m1f16.h
DEPENDS
.expxf16
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.multiply_add
libc.src.__support.FPUtil.polyeval
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.macros.optimization
libc.src.__support.macros.properties.cpu_features
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
expm1
SRCS
Expand Down
47 changes: 3 additions & 44 deletions libc/src/math/generic/exp10f16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,6 @@ static constexpr fputil::ExceptValues<float16, N_EXP10F16_EXCEPTS>
#endif
}};

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log2(10), SG, RN);
static constexpr float LOG2F_10 = 0x1.a934fp+1f;

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log10(2), SG, RN);
static constexpr float LOG10F_2 = 0x1.344136p-2f;

LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
FPBits x_bits(x);
Expand Down Expand Up @@ -132,40 +122,9 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
if (auto r = EXP10F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();

// For -8 < x < 5, to compute 10^x, we perform the following range reduction:
// find hi, mid, lo, such that:
// x = (hi + mid) * log2(10) + lo, in which
// hi is an integer,
// mid * 2^3 is an integer,
// -2^(-4) <= lo < 2^(-4).
// In particular,
// hi + mid = round(x * 2^3) * 2^(-3).
// Then,
// 10^x = 10^(hi + mid + lo) = 2^((hi + mid) * log2(10)) + 10^lo
// We store 2^mid in the lookup table EXP2_MID_BITS, and compute 2^hi * 2^mid
// by adding hi to the exponent field of 2^mid. 10^lo is computed using a
// degree-4 minimax polynomial generated by Sollya.

float xf = x;
float kf = fputil::nearest_integer(xf * (LOG2F_10 * 0x1.0p+3f));
int x_hi_mid = static_cast<int>(kf);
int x_hi = x_hi_mid >> 3;
int x_mid = x_hi_mid & 0x7;
// lo = x - (hi + mid) = round(x * 2^3 * log2(10)) * log10(2) * (-2^(-3)) + x
float lo = fputil::multiply_add(kf, LOG10F_2 * -0x1.0p-3f, xf);

uint32_t exp2_hi_mid_bits =
EXP2_MID_BITS[x_mid] +
static_cast<uint32_t>(x_hi << fputil::FPBits<float>::FRACTION_LEN);
float exp2_hi_mid = fputil::FPBits<float>(exp2_hi_mid_bits).get_val();
// Degree-4 minimax polynomial generated by Sollya with the following
// commands:
// > display = hexadecimal;
// > P = fpminimax((10^x - 1)/x, 3, [|SG...|], [-2^-4, 2^-4]);
// > 1 + x * P;
float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f,
0x1.04b434p+1f, 0x1.2bcf9ep+0f);
return fputil::cast<float16>(exp2_hi_mid * exp10_lo);
// 10^x = 2^((hi + mid) * log2(10)) * 10^lo
auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x);
return static_cast<float16>(exp2_hi_mid * exp10_lo);
}

} // namespace LIBC_NAMESPACE_DECL
163 changes: 163 additions & 0 deletions libc/src/math/generic/exp10m1f16.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//===-- Half-precision 10^x - 1 function ----------------------------------===//
//
// 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 "src/math/exp10m1f16.h"
#include "expxf16.h"
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/macros/properties/cpu_features.h"

namespace LIBC_NAMESPACE_DECL {

static constexpr fputil::ExceptValues<float16, 3> EXP10M1F16_EXCEPTS_LO = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.5c4p-4, exp10m1f16(x) = 0x1.bacp-3 (RZ)
{0x2d71U, 0x32ebU, 1U, 0U, 0U},
// x = -0x1.5ep-13, exp10m1f16(x) = -0x1.92cp-12 (RZ)
{0x8978U, 0x8e4bU, 0U, 1U, 0U},
// x = -0x1.e2p-10, exp10m1f16(x) = -0x1.14cp-8 (RZ)
{0x9788U, 0x9c53U, 0U, 1U, 0U},
}};

#ifdef LIBC_TARGET_CPU_HAS_FMA
static constexpr size_t N_EXP10M1F16_EXCEPTS_HI = 3;
#else
static constexpr size_t N_EXP10M1F16_EXCEPTS_HI = 6;
#endif

static constexpr fputil::ExceptValues<float16, N_EXP10M1F16_EXCEPTS_HI>
EXP10M1F16_EXCEPTS_HI = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.8f4p-2, exp10m1f16(x) = 0x1.744p+0 (RZ)
{0x363dU, 0x3dd1U, 1U, 0U, 0U},
// x = 0x1.95cp-2, exp10m1f16(x) = 0x1.7d8p+0 (RZ)
{0x3657U, 0x3df6U, 1U, 0U, 0U},
// x = 0x1.d04p-2, exp10m1f16(x) = 0x1.d7p+0 (RZ)
{0x3741U, 0x3f5cU, 1U, 0U, 1U},
#ifndef LIBC_TARGET_CPU_HAS_FMA
// x = 0x1.0cp+1, exp10m1f16(x) = 0x1.ec4p+6 (RZ)
{0x4030U, 0x57b1U, 1U, 0U, 1U},
// x = 0x1.1b8p+1, exp10m1f16(x) = 0x1.45cp+7 (RZ)
{0x406eU, 0x5917U, 1U, 0U, 1U},
// x = 0x1.2f4p+2, exp10m1f16(x) = 0x1.ab8p+15 (RZ)
{0x44bdU, 0x7aaeU, 1U, 0U, 1U},
#endif
}};

LLVM_LIBC_FUNCTION(float16, exp10m1f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
FPBits x_bits(x);

uint16_t x_u = x_bits.uintval();
uint16_t x_abs = x_u & 0x7fffU;

// When |x| <= 2^(-3), or |x| >= 11 * log10(2), or x is NaN.
if (LIBC_UNLIKELY(x_abs <= 0x3000U || x_abs >= 0x429fU)) {
// exp10m1(NaN) = NaN
if (x_bits.is_nan()) {
if (x_bits.is_signaling_nan()) {
fputil::raise_except_if_required(FE_INVALID);
return FPBits::quiet_nan().get_val();
}

return x;
}

// When x >= 16 * log10(2).
if (x_u >= 0x44d1U && x_bits.is_pos()) {
// exp10m1(+inf) = +inf
if (x_bits.is_inf())
return FPBits::inf().get_val();

switch (fputil::quick_get_round()) {
case FE_TONEAREST:
case FE_UPWARD:
fputil::set_errno_if_required(ERANGE);
fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
return FPBits::inf().get_val();
default:
return FPBits::max_normal().get_val();
}
}

// When x < -11 * log10(2).
if (x_u > 0xc29fU) {
// exp10m1(-inf) = -1
if (x_bits.is_inf())
return FPBits::one(Sign::NEG).get_val();

// When x >= -0x1.ce4p+1, round(10^x - 1, HP, RN) = -0x1.ffcp-1.
if (x_u <= 0xc339U) {
return fputil::round_result_slightly_down(
fputil::cast<float16>(-0x1.ffcp-1));
}

// When x < -0x1.ce4p+1, round(10^x - 1, HP, RN) = -1.
switch (fputil::quick_get_round()) {
case FE_TONEAREST:
case FE_DOWNWARD:
return FPBits::one(Sign::NEG).get_val();
default:
return fputil::cast<float16>(-0x1.ffcp-1);
}
}

// When |x| <= 2^(-3).
if (x_abs <= 0x3000U) {
if (auto r = EXP10M1F16_EXCEPTS_LO.lookup(x_u);
LIBC_UNLIKELY(r.has_value()))
return r.value();

float xf = x;
// Degree-5 minimax polynomial generated by Sollya with the following
// commands:
// > display = hexadecimal;
// > P = fpminimax((10^x - 1)/x, 4, [|SG...|], [-2^-3, 2^-3]);
// > x * P;
return fputil::cast<float16>(
xf * fputil::polyeval(xf, 0x1.26bb1cp+1f, 0x1.5351c8p+1f,
0x1.04704p+1f, 0x1.2ce084p+0f, 0x1.14a6bep-1f));
}
}

// When x is 1, 2, or 3. These are hard-to-round cases with exact results.
// 10^4 - 1 = 9'999 is not exactly representable as a float16, but luckily the
// polynomial approximation gives the correct result for x = 4 in all
// rounding modes.
if (LIBC_UNLIKELY((x_u & ~(0x3c00U | 0x4000U | 0x4200U | 0x4400U)) == 0)) {
switch (x_u) {
case 0x3c00U: // x = 1.0f16
return fputil::cast<float16>(9.0);
case 0x4000U: // x = 2.0f16
return fputil::cast<float16>(99.0);
case 0x4200U: // x = 3.0f16
return fputil::cast<float16>(999.0);
}
}

if (auto r = EXP10M1F16_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();

// exp10(x) = exp2((hi + mid) * log2(10)) * exp10(lo)
auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x);
// exp10m1(x) = exp2((hi + mid) * log2(lo)) * exp10(lo) - 1
return fputil::cast<float16>(
fputil::multiply_add(exp2_hi_mid, exp10_lo, -1.0f));
}

} // namespace LIBC_NAMESPACE_DECL
47 changes: 47 additions & 0 deletions libc/src/math/generic/expxf16.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,53 @@ LIBC_INLINE ExpRangeReduction exp2_range_reduction(float16 x) {
return {exp2_hi_mid, exp2_lo};
}

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log2(10), SG, RN);
static constexpr float LOG2F_10 = 0x1.a934fp+1f;

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log10(2), SG, RN);
static constexpr float LOG10F_2 = 0x1.344136p-2f;

LIBC_INLINE ExpRangeReduction exp10_range_reduction(float16 x) {
// For -8 < x < 5, to compute 10^x, we perform the following range reduction:
// find hi, mid, lo, such that:
// x = (hi + mid) * log2(10) + lo, in which
// hi is an integer,
// mid * 2^3 is an integer,
// -2^(-4) <= lo < 2^(-4).
// In particular,
// hi + mid = round(x * 2^3) * 2^(-3).
// Then,
// 10^x = 10^(hi + mid + lo) = 2^((hi + mid) * log2(10)) + 10^lo
// We store 2^mid in the lookup table EXP2_MID_BITS, and compute 2^hi * 2^mid
// by adding hi to the exponent field of 2^mid. 10^lo is computed using a
// degree-4 minimax polynomial generated by Sollya.

float xf = x;
float kf = fputil::nearest_integer(xf * (LOG2F_10 * 0x1.0p+3f));
int x_hi_mid = static_cast<int>(kf);
int x_hi = x_hi_mid >> 3;
int x_mid = x_hi_mid & 0x7;
// lo = x - (hi + mid) = round(x * 2^3 * log2(10)) * log10(2) * (-2^(-3)) + x
float lo = fputil::multiply_add(kf, LOG10F_2 * -0x1.0p-3f, xf);

uint32_t exp2_hi_mid_bits =
EXP2_MID_BITS[x_mid] +
static_cast<uint32_t>(x_hi << fputil::FPBits<float>::FRACTION_LEN);
float exp2_hi_mid = fputil::FPBits<float>(exp2_hi_mid_bits).get_val();
// Degree-4 minimax polynomial generated by Sollya with the following
// commands:
// > display = hexadecimal;
// > P = fpminimax((10^x - 1)/x, 3, [|SG...|], [-2^-4, 2^-4]);
// > 1 + x * P;
float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f,
0x1.04b434p+1f, 0x1.2bcf9ep+0f);
return {exp2_hi_mid, exp10_lo};
}

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPXF16_H
11 changes: 11 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,17 @@ add_fp_unittest(
libc.src.math.exp10f16
)

add_fp_unittest(
exp10m1f16_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
exp10m1f16_test.cpp
DEPENDS
libc.src.math.exp10m1f16
)

add_fp_unittest(
copysign_test
SUITE
Expand Down
40 changes: 40 additions & 0 deletions libc/test/src/math/exp10m1f16_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===-- Exhaustive test for exp10m1f16 ------------------------------------===//
//
// 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 "src/math/exp10m1f16.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

using LlvmLibcExp10m1f16Test = LIBC_NAMESPACE::testing::FPTest<float16>;

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;

// Range: [0, Inf];
static constexpr uint16_t POS_START = 0x0000U;
static constexpr uint16_t POS_STOP = 0x7c00U;

// Range: [-Inf, 0];
static constexpr uint16_t NEG_START = 0x8000U;
static constexpr uint16_t NEG_STOP = 0xfc00U;

TEST_F(LlvmLibcExp10m1f16Test, PositiveRange) {
for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
float16 x = FPBits(v).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp10m1, x,
LIBC_NAMESPACE::exp10m1f16(x), 0.5);
}
}

TEST_F(LlvmLibcExp10m1f16Test, NegativeRange) {
for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
float16 x = FPBits(v).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp10m1, x,
LIBC_NAMESPACE::exp10m1f16(x), 0.5);
}
}
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.cast
)

add_fp_unittest(
exp10m1f16_test
SUITE
libc-math-smoke-tests
SRCS
exp10m1f16_test.cpp
DEPENDS
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.exp10m1f16
libc.src.__support.FPUtil.cast
)

add_fp_unittest(
copysign_test
SUITE
Expand Down
113 changes: 113 additions & 0 deletions libc/test/src/math/smoke/exp10m1f16_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//===-- Unittests for exp10m1f16 ------------------------------------------===//
//
// 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 "hdr/fenv_macros.h"
#include "src/__support/FPUtil/cast.h"
#include "src/errno/libc_errno.h"
#include "src/math/exp10m1f16.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

using LlvmLibcExp10m1f16Test = LIBC_NAMESPACE::testing::FPTest<float16>;

TEST_F(LlvmLibcExp10m1f16Test, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::exp10m1f16(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::exp10m1f16(sNaN),
FE_INVALID);
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::exp10m1f16(inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(neg_inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::exp10m1f16(zero));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::exp10m1f16(neg_zero));
EXPECT_MATH_ERRNO(0);
}

TEST_F(LlvmLibcExp10m1f16Test, Overflow) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ_WITH_EXCEPTION(inf, LIBC_NAMESPACE::exp10m1f16(max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

// round(16 * log10(2), HP, RN);
float16 x = LIBC_NAMESPACE::fputil::cast<float16>(0x1.344p+2);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
inf, LIBC_NAMESPACE::exp10m1f16(x), FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
inf, LIBC_NAMESPACE::exp10m1f16(x), FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
max_normal, LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
max_normal, LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);
EXPECT_MATH_ERRNO(0);
}

TEST_F(LlvmLibcExp10m1f16Test, ResultNearNegOne) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ_WITH_EXCEPTION(LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(neg_max_normal),
FE_INEXACT);

// round(-11 * log10(2), HP, RD);
float16 x = LIBC_NAMESPACE::fputil::cast<float16>(-0x1.a8p+1);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

// Next float16 value below -0x1.ce4p+1.
x = LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ce8p+1);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);
}
25 changes: 25 additions & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,29 @@ class MPFRNumber {
return result;
}

MPFRNumber exp10m1() const {
// TODO: Only use mpfr_exp10m1 once CI and buildbots get MPFR >= 4.2.0.
#if MPFR_VERSION_MAJOR > 4 || \
(MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2)
MPFRNumber result(*this);
mpfr_exp10m1(result.value, value, mpfr_rounding);
return result;
#else
unsigned int prec = mpfr_precision * 3;
MPFRNumber result(*this, prec);

MPFRNumber ln10(10.0f, prec);
// log(10)
mpfr_log(ln10.value, ln10.value, mpfr_rounding);
// x * log(10)
mpfr_mul(result.value, value, ln10.value, mpfr_rounding);
// e^(x * log(10)) - 1
int ex = mpfr_expm1(result.value, result.value, mpfr_rounding);
mpfr_subnormalize(result.value, ex, mpfr_rounding);
return result;
#endif
}

MPFRNumber expm1() const {
MPFRNumber result(*this);
mpfr_expm1(result.value, value, mpfr_rounding);
Expand Down Expand Up @@ -744,6 +767,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
return mpfrInput.exp2m1();
case Operation::Exp10:
return mpfrInput.exp10();
case Operation::Exp10m1:
return mpfrInput.exp10m1();
case Operation::Expm1:
return mpfrInput.expm1();
case Operation::Floor:
Expand Down
1 change: 1 addition & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ enum class Operation : int {
Exp2,
Exp2m1,
Exp10,
Exp10m1,
Expm1,
Floor,
Log,
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
"`LWG3672 <https://wg21.link/LWG3672>`__","``common_iterator::operator->()`` should return by value","2022-07 (Virtual)","|Complete|","19.0",""
"`LWG3683 <https://wg21.link/LWG3683>`__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","2022-07 (Virtual)","|Complete|","20.0",""
"`LWG3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","2022-07 (Virtual)","|Complete|","16.0",""
"`LWG3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","","",""
"`LWG3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20.0",""
"`LWG3701 <https://wg21.link/LWG3701>`__","Make ``formatter<remove_cvref_t<const charT[N]>, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15.0",""
"`LWG3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","","",""
"`LWG3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","2022-07 (Virtual)","|Complete|","16.0",""
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"`P1642R11 <https://wg21.link/P1642R11>`__","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","2022-07 (Virtual)","","",""
"`P1899R3 <https://wg21.link/P1899R3>`__","``stride_view``","2022-07 (Virtual)","","",""
"`P2093R14 <https://wg21.link/P2093R14>`__","Formatted output","2022-07 (Virtual)","|Complete|","18.0",""
"`P2165R4 <https://wg21.link/P2165R4>`__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","","",""
"`P2165R4 <https://wg21.link/P2165R4>`__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","|Partial|","","Only the part for ``zip_view`` is implemented."
"`P2278R4 <https://wg21.link/P2278R4>`__","``cbegin`` should always return a constant iterator","2022-07 (Virtual)","","",""
"`P2286R8 <https://wg21.link/P2286R8>`__","Formatting Ranges","2022-07 (Virtual)","|Complete|","16.0",""
"`P2291R3 <https://wg21.link/P2291R3>`__","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ``<charconv>`` Header","2022-07 (Virtual)","|Complete|","16.0",""
Expand Down
55 changes: 8 additions & 47 deletions libcxx/include/__ranges/zip_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include <__utility/forward.h>
#include <__utility/integer_sequence.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#include <tuple>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Expand All @@ -58,22 +57,11 @@ concept __zip_is_common =
(!(bidirectional_range<_Ranges> && ...) && (common_range<_Ranges> && ...)) ||
((random_access_range<_Ranges> && ...) && (sized_range<_Ranges> && ...));

template <typename _Tp, typename _Up>
auto __tuple_or_pair_test() -> pair<_Tp, _Up>;

template <typename... _Types>
requires(sizeof...(_Types) != 2)
auto __tuple_or_pair_test() -> tuple<_Types...>;

template <class... _Types>
using __tuple_or_pair = decltype(__tuple_or_pair_test<_Types...>());

template <class _Fun, class _Tuple>
_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tuple) {
return std::apply(
[&]<class... _Types>(_Types&&... __elements) {
return __tuple_or_pair<invoke_result_t<_Fun&, _Types>...>(
std::invoke(__f, std::forward<_Types>(__elements))...);
return tuple<invoke_result_t<_Fun&, _Types>...>(std::invoke(__f, std::forward<_Types>(__elements))...);
},
std::forward<_Tuple>(__tuple));
}
Expand All @@ -88,7 +76,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tup
}

template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices>
_LIBCPP_HIDE_FROM_ABI constexpr __tuple_or_pair<
_LIBCPP_HIDE_FROM_ABI constexpr tuple<
invoke_result_t<_Fun&,
typename tuple_element<_Indices, remove_cvref_t<_Tuple1>>::type,
typename tuple_element<_Indices, remove_cvref_t<_Tuple2>>::type>...>
Expand Down Expand Up @@ -250,10 +238,9 @@ template <input_range... _Views>
requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
template <bool _Const>
class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> {
__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current_;
tuple<iterator_t<__maybe_const<_Const, _Views>>...> __current_;

_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(
__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(tuple<iterator_t<__maybe_const<_Const, _Views>>...> __current)
: __current_(std::move(__current)) {}

template <bool>
Expand All @@ -266,7 +253,7 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base

public:
using iterator_concept = decltype(__get_zip_view_iterator_tag<_Const, _Views...>());
using value_type = __tuple_or_pair<range_value_t<__maybe_const<_Const, _Views>>...>;
using value_type = tuple<range_value_t<__maybe_const<_Const, _Views>>...>;
using difference_type = common_type_t<range_difference_t<__maybe_const<_Const, _Views>>...>;

_LIBCPP_HIDE_FROM_ABI __iterator() = default;
Expand Down Expand Up @@ -340,33 +327,8 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base
}
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return __x.__current_ < __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return __y < __x;
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return !(__y < __x);
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return !(__x < __y);
}

_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...> &&
(three_way_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...)
requires __zip_all_random_access<_Const, _Views...>
{
return __x.__current_ <=> __y.__current_;
}
Expand Down Expand Up @@ -427,10 +389,9 @@ template <input_range... _Views>
requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
template <bool _Const>
class zip_view<_Views...>::__sentinel {
__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end_;
tuple<sentinel_t<__maybe_const<_Const, _Views>>...> __end_;

_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(
__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(tuple<sentinel_t<__maybe_const<_Const, _Views>>...> __end)
: __end_(__end) {}

friend class zip_view<_Views...>;
Expand Down
3 changes: 0 additions & 3 deletions libcxx/include/__split_buffer
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,6 @@ public:
pointer __end_;
_LIBCPP_COMPRESSED_PAIR(pointer, __end_cap_, allocator_type, __alloc_);

using __alloc_ref = __add_lvalue_reference_t<allocator_type>;
using __alloc_const_ref = __add_lvalue_reference_t<allocator_type>;

__split_buffer(const __split_buffer&) = delete;
__split_buffer& operator=(const __split_buffer&) = delete;

Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/future
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ public:
_LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Arg&& __arg);

_LIBCPP_HIDE_FROM_ABI _Rp move();
_LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<_Rp> copy();
_LIBCPP_HIDE_FROM_ABI _Rp& copy();
};

template <class _Rp>
Expand Down Expand Up @@ -636,7 +636,7 @@ _Rp __assoc_state<_Rp>::move() {
}

template <class _Rp>
__add_lvalue_reference_t<_Rp> __assoc_state<_Rp>::copy() {
_Rp& __assoc_state<_Rp>::copy() {
unique_lock<mutex> __lk(this->__mut_);
this->__sub_wait(__lk);
if (this->__exception_ != nullptr)
Expand Down
4 changes: 0 additions & 4 deletions libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ constexpr bool test() {
std::ranges::zip_view<std::ranges::zip_view<SizedRandomAccessView, SizedRandomAccessView>>> decltype(auto) v2 =
std::views::zip(v);

#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v2)>, std::tuple<std::pair<int&, int&>>>);
#else
static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v2)>, std::tuple<std::tuple<int&, int&>>>);
#endif
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,8 @@ constexpr bool test() {
using View = std::ranges::zip_view<DefaultConstructibleView, DefaultConstructibleView>;
View v = View(); // the default constructor is not explicit
assert(v.size() == 3);
auto it = v.begin();
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
using Value = std::pair<const int&, const int&>;
#else
auto it = v.begin();
using Value = std::tuple<const int&, const int&>;
#endif
assert(*it++ == Value(buff[0], buff[0]));
assert(*it++ == Value(buff[1], buff[1]));
assert(*it == Value(buff[2], buff[2]));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,8 @@

// friend constexpr bool operator==(const iterator& x, const iterator& y)
// requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
// friend constexpr bool operator<(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr bool operator>(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr bool operator<=(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr bool operator>=(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr auto operator<=>(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...> &&
// (three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
// requires all-random-access<Const, Views...>;

#include <ranges>
#include <compare>
Expand Down Expand Up @@ -165,12 +156,7 @@ constexpr bool test() {
using Subrange = std::ranges::subrange<It>;
static_assert(!std::three_way_comparable<It>);
using R = std::ranges::zip_view<Subrange, Subrange>;
#ifdef _LIBCPP_VERSION
// libc++ hasn't implemented LWG-3692 "zip_view::iterator's operator<=> is overconstrained"
static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);
#else
static_assert(std::three_way_comparable<std::ranges::iterator_t<R>>);
#endif

int a[] = {1, 2, 3, 4};
int b[] = {5, 6, 7, 8, 9};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@ constexpr bool test() {
auto [x, y] = *it;
assert(&x == &(a[0]));
assert(&y == &(b[0]));
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(*it), std::pair<int&, double&>>);
#else
static_assert(std::is_same_v<decltype(*it), std::tuple<int&, double&>>);
#endif

x = 5;
y = 0.1;
Expand All @@ -70,11 +66,7 @@ constexpr bool test() {
auto it = v.begin();
assert(&(std::get<0>(*it)) == &(a[0]));
assert(&(std::get<1>(*it)) == &(a[0]));
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(*it), std::pair<int&, int const&>>);
#else
static_assert(std::is_same_v<decltype(*it), std::tuple<int&, int const&>>);
#endif
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,15 @@ struct ConstVeryDifferentRange {
void test() {
int buffer[] = {1, 2, 3, 4};
{
// 2 views should have pair value_type
// 2 views should have 2-tuple value_type
// random_access_iterator_tag
std::ranges::zip_view v(buffer, buffer);
using Iter = decltype(v.begin());

static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>);
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<Iter::value_type, std::pair<int, int>>);
#else
static_assert(std::is_same_v<Iter::value_type, std::tuple<int, int>>);
#endif
static_assert(HasIterCategory<Iter>);
}

Expand Down Expand Up @@ -124,11 +120,7 @@ void test() {
static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>);
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<Iter::value_type, std::pair<int, std::pair<int, int>>>);
#else
static_assert(std::is_same_v<Iter::value_type, std::tuple<int, std::tuple<int, int>>>);
#endif
static_assert(HasIterCategory<Iter>);
}

Expand Down Expand Up @@ -169,11 +161,7 @@ void test() {
// value_type of multiple views with different value_type
std::ranges::zip_view v{foos, bars};
using Iter = decltype(v.begin());
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<Iter::value_type, std::pair<Foo, Bar>>);
#else
static_assert(std::is_same_v<Iter::value_type, std::tuple<Foo, Bar>>);
#endif
}

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ constexpr bool test() {
assert(it[2] == *(it + 2));
assert(it[4] == *(it + 4));

#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(it[2]), std::pair<int&, int>>);
#else
static_assert(std::is_same_v<decltype(it[2]), std::tuple<int&, int>>);
#endif
}

{
Expand All @@ -42,11 +38,7 @@ constexpr bool test() {
assert(it[2] == *(it + 2));
assert(it[4] == *(it + 4));

#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(it[2]), std::pair<int&, int&>>);
#else
static_assert(std::is_same_v<decltype(it[2]), std::tuple<int&, int&>>);
#endif
}

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,7 @@ def run_vscode(dbg, args, options):
def main():
parser = optparse.OptionParser(
description=(
"A testing framework for the Visual Studio Code Debug " "Adaptor protocol"
"A testing framework for the Visual Studio Code Debug Adaptor protocol"
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,15 @@ NativeRegisterContextFreeBSD_arm64::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &reg_value) {
Status error;

if (!reg_info) {
error = Status::FromErrorString("reg_info NULL");
return error;
}
if (!reg_info)
return Status::FromErrorString("reg_info NULL");

const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];

if (reg == LLDB_INVALID_REGNUM)
return Status("no lldb regnum for %s", reg_info && reg_info->name
? reg_info->name
: "<unknown register>");
return Status::FromErrorStringWithFormat(
"no lldb regnum for %s",
reg_info && reg_info->name ? reg_info->name : "<unknown register>");

uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
error = ReadRegisterSet(set);
Expand All @@ -147,14 +145,14 @@ Status NativeRegisterContextFreeBSD_arm64::WriteRegister(
Status error;

if (!reg_info)
return Status("reg_info NULL");
return Status::FromErrorString("reg_info NULL");

const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];

if (reg == LLDB_INVALID_REGNUM)
return Status("no lldb regnum for %s", reg_info && reg_info->name
? reg_info->name
: "<unknown register>");
return Status::FromErrorStringWithFormat(
"no lldb regnum for %s",
reg_info && reg_info->name ? reg_info->name : "<unknown register>");

uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
error = ReadRegisterSet(set);
Expand Down
56 changes: 39 additions & 17 deletions lldb/source/Utility/DiagnosticsRendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,7 @@ void RenderDiagnosticDetails(Stream &stream,
spacer = "";
}

// Print a line with caret indicator(s) below the lldb prompt + command.
const size_t padding = *offset_in_command;
stream << std::string(padding, ' ');

size_t offset = 1;
// Partition the diagnostics.
std::vector<DiagnosticDetail> remaining_details, other_details,
hidden_details;
for (const DiagnosticDetail &detail : details) {
Expand All @@ -98,14 +94,39 @@ void RenderDiagnosticDetails(Stream &stream,
continue;
}

auto &loc = *detail.source_location;
remaining_details.push_back(detail);
if (offset > loc.column)
continue;
stream << std::string(loc.column - offset, ' ') << cursor;
for (unsigned i = 0; i + 1 < loc.length; ++i)
stream << underline;
offset = loc.column + 1;
}

// Sort the diagnostics.
auto sort = [](auto &ds) {
llvm::sort(ds.begin(), ds.end(), [](auto &d1, auto &d2) {
auto l1 = d1.source_location.value_or(DiagnosticDetail::SourceLocation{});
auto l2 = d2.source_location.value_or(DiagnosticDetail::SourceLocation{});
return std::pair(l1.line, l2.column) < std::pair(l1.line, l2.column);
});
};
sort(remaining_details);
sort(other_details);
sort(hidden_details);

// Print a line with caret indicator(s) below the lldb prompt + command.
const size_t padding = *offset_in_command;
stream << std::string(padding, ' ');
{
size_t x_pos = 1;
for (const DiagnosticDetail &detail : remaining_details) {
auto &loc = *detail.source_location;

if (x_pos > loc.column)
continue;

stream << std::string(loc.column - x_pos, ' ') << cursor;
++x_pos;
for (unsigned i = 0; i + 1 < loc.length; ++i) {
stream << underline;
++x_pos;
}
}
}
stream << '\n';

Expand All @@ -117,18 +138,19 @@ void RenderDiagnosticDetails(Stream &stream,
// Get the information to print this detail and remove it from the stack.
// Print all the lines for all the other messages first.
stream << std::string(padding, ' ');
size_t offset = 1;
size_t x_pos = 1;
for (auto &remaining_detail :
llvm::ArrayRef(remaining_details).drop_back(1)) {
uint16_t column = remaining_detail.source_location->column;
stream << std::string(column - offset, ' ') << vbar;
offset = column + 1;
if (x_pos <= column)
stream << std::string(column - x_pos, ' ') << vbar;
x_pos = column + 1;
}

// Print the line connecting the ^ with the error message.
uint16_t column = detail->source_location->column;
if (offset <= column)
stream << std::string(column - offset, ' ') << joint << hbar << spacer;
if (x_pos <= column)
stream << std::string(column - x_pos, ' ') << joint << hbar << spacer;

// Print a colorized string based on the message's severity type.
PrintSeverity(stream, detail->severity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
class TestCase(TestBase):
@add_test_categories(["libc++"])
@skipIf(compiler=no_match("clang"))
@skipIfLinux # https://discourse.llvm.org/t/lldb-test-failures-on-linux/80095
def test(self):
self.build()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class TestDbgInfoContentVector(TestBase):
@skipIf(compiler="clang", compiler_version=["<", "12.0"])
@skipIf(macos_version=["<", "14.0"])
@skipIfDarwin # https://github.com/llvm/llvm-project/issues/106475
@skipIfLinux # https://discourse.llvm.org/t/lldb-test-failures-on-linux/80095
def test(self):
self.build()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
class TestVectorOfVectors(TestBase):
@add_test_categories(["libc++"])
@skipIf(compiler=no_match("clang"))
@skipIfLinux # https://discourse.llvm.org/t/lldb-test-failures-on-linux/80095
def test(self):
self.build()

Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/commands/expression/top-level/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ all: dummy
include Makefile.rules

dummy: dummy.cpp
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
CXX_SOURCES=dummy.cpp EXE=dummy

4 changes: 2 additions & 2 deletions lldb/test/API/commands/expression/weak_symbols/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ a.out: libdylib.dylib
include Makefile.rules

libdylib.dylib: dylib.c
$(MAKE) -C $(BUILDDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" -C $(BUILDDIR) -f $(MAKEFILE_RULES) \
C_SOURCES= DYLIB_C_SOURCES=dylib.c DYLIB_NAME=dylib \
CFLAGS_EXTRAS=-DHAS_THEM LD_EXTRAS=-dynamiclib

hidden/libdylib.dylib:
mkdir hidden
$(MAKE) -C $(BUILDDIR)/hidden -f $(MAKEFILE_RULES) \
"$(MAKE)" -C $(BUILDDIR)/hidden -f $(MAKEFILE_RULES) \
C_SOURCES= DYLIB_C_SOURCES=dylib.c DYLIB_NAME=dylib \
LD_EXTRAS=-dynamiclib
2 changes: 1 addition & 1 deletion lldb/test/API/commands/target/create-deps/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ a.out: libload_a
include Makefile.rules

libload_a:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=load_a DYLIB_CXX_SOURCES=a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CXX_SOURCES := main.cpp
USE_LIBDL := 1

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=lib_b
all: lib_b

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ C_SOURCES := main.c
USE_LIBDL := 1

other:
$(MAKE) -f $(MAKEFILE_RULES) C_SOURCES=other.c EXE=other
"$(MAKE)" -f $(MAKEFILE_RULES) C_SOURCES=other.c EXE=other
all: other

include Makefile.rules
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/exec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ all: secondprog
include Makefile.rules

secondprog: secondprog.cpp
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
CXX_SOURCES=secondprog.cpp EXE=secondprog
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/jitloader_gdb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ all: a.out simple
include Makefile.rules

simple:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
C_SOURCES=simple.c EXE=simple
4 changes: 2 additions & 2 deletions lldb/test/API/functionalities/limit-debug-info/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ include Makefile.rules
a.out: libone libtwo

libone:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=one.cpp DYLIB_NAME=one \
CFLAGS_EXTRAS="$(ONE_CXXFLAGS)"

libtwo: libone
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=two.cpp DYLIB_NAME=two \
CFLAGS_EXTRAS="$(TWO_CXXFLAGS)" LD_EXTRAS="-L. -lone"
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/load_after_attach/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CXX_SOURCES := main.cpp
USE_LIBDL := 1

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=lib_b
all: lib_b

Expand Down
6 changes: 3 additions & 3 deletions lldb/test/API/functionalities/load_lazy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ else
endif

t1: t2_0
$(MAKE) VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=t1.c DYLIB_NAME=t1 LD_EXTRAS="-L. $(LINKFLAGS)"

t2_0:
$(MAKE) VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=t2_0.c DYLIB_NAME=t2_0

t2_1:
$(MAKE) VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=t2_1.c DYLIB_NAME=t2_1
10 changes: 5 additions & 5 deletions lldb/test/API/functionalities/load_unload/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@ a.out: lib_b lib_a lib_c lib_d hidden_lib_d
include Makefile.rules

lib_a: lib_b
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=loadunload_a \
LD_EXTRAS="-L. -lloadunload_b"

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=loadunload_b

lib_c:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=loadunload_c

lib_d:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload_d
ifeq ($(OS),Darwin)
install_name_tool -id @executable_path/libloadunload_d.dylib libloadunload_d.dylib
endif

hidden_lib_d: hidden
$(MAKE) VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload_d
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/load_using_paths/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ all: hidden_lib a.out
include Makefile.rules

hidden_lib:
$(MAKE) VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload

2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/scripted_process/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CXXFLAGS_EXTRAS := -target $(TRIPLE)
all: libbaz.dylib a.out

libbaz.dylib: baz.cpp
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=baz DYLIB_CXX_SOURCES=baz.cpp

include Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ a.out: lib_a lib_b
include Makefile.rules

lib_a:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=load_a

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=load_b


Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ a.out: lib_One lib_Two
lib_One: lib_Two

lib_%:
$(MAKE) VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk DSYMUTIL=$(DSYMUTIL)
"$(MAKE)" VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk DSYMUTIL=$(DSYMUTIL)
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
CXX_SOURCES := main.cpp
LD_EXTRAS := -L. -l_d -l_c -l_a -l_b
LD_EXTRAS := -L. -l_d -l_c -l_a -l_b

a.out: lib_b lib_a lib_c lib_d

include Makefile.rules

lib_a: lib_b
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \
LD_EXTRAS="-L. -l_b"
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \
LD_EXTRAS="-L. -l_b"

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b

lib_c:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c

lib_d:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d
2 changes: 1 addition & 1 deletion lldb/test/API/lang/c/conflicting-symbol/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ include Makefile.rules
a.out: lib_One lib_Two

lib_%:
$(MAKE) VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk
"$(MAKE)" VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk
2 changes: 1 addition & 1 deletion lldb/test/API/lang/cpp/incomplete-types/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ main.o: CFLAGS_EXTRAS = -flimit-debug-info

limit: a.o main.o
mkdir -p build_limit
$(MAKE) -C $(BUILDDIR)/build_limit -f $(MAKEFILE_RULES) \
"$(MAKE)" -C $(BUILDDIR)/build_limit -f $(MAKEFILE_RULES) \
EXE=../limit CXX_SOURCES="length.cpp ../a.o ../main.o" \
CFLAGS_EXTRAS=-flimit-debug-info NO_LIMIT_DEBUG_INFO_FLAGS=""

4 changes: 2 additions & 2 deletions lldb/test/API/lang/cpp/namespace_definitions/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ a.out: liba libb
include Makefile.rules

liba:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=a DYLIB_CXX_SOURCES=a.cpp

libb:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=b DYLIB_CXX_SOURCES=b.cpp

6 changes: 0 additions & 6 deletions lldb/test/API/lang/cpp/stl/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
CXX_SOURCES := main.cpp

ifneq ($(OS),Darwin)
USE_LIBSTDCPP := 1
else
USE_SYSTEM_STDLIB := 1
endif

include Makefile.rules
4 changes: 2 additions & 2 deletions lldb/test/API/lang/objc/conflicting-definition/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ include Makefile.rules

libTest.dylib: Test/Test.m
mkdir -p Test
$(MAKE) MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
"$(MAKE)" MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=Test DYLIB_OBJC_SOURCES=Test/Test.m \
LD_EXTRAS="-lobjc -framework Foundation" \
CFLAGS_EXTRAS=-I$(SRCDIR)

libTestExt.dylib: TestExt/TestExt.m
mkdir -p TestExt
$(MAKE) MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
"$(MAKE)" MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=TestExt DYLIB_OBJC_SOURCES=TestExt/TestExt.m \
LD_EXTRAS="-lobjc -framework Foundation -lTest -L." \
CFLAGS_EXTRAS=-I$(SRCDIR)
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/lang/objc/modules-hash-mismatch/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ USE_PRIVATE_MODULE_CACHE = YES
.PHONY: update-module

all: $(EXE)
$(MAKE) -f $(SRCDIR)/Makefile update-module
"$(MAKE)" -f $(SRCDIR)/Makefile update-module

include Makefile.rules

Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/delay-init-dependency/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ all: build-libfoo a.out
include Makefile.rules

build-libfoo: foo.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=foo.c DYLIB_NAME=foo DYLIB_ONLY=YES
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/expedited-thread-pcs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ all: build-libfoo a.out
include Makefile.rules

build-libfoo: foo.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=foo.c DYLIB_NAME=foo DYLIB_ONLY=YES

4 changes: 2 additions & 2 deletions lldb/test/API/macosx/indirect_symbol/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ all: build-libindirect build-libreepxoprt a.out
include Makefile.rules

build-libindirect: indirect.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=indirect.c DYLIB_NAME=indirect DYLIB_ONLY=YES \
LD_EXTRAS="-Wl,-image_base,0x200000000"

build-libreepxoprt: reexport.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=reexport.c DYLIB_NAME=reexport DYLIB_ONLY=YES \
LD_EXTRAS="-L. -lindirect -Wl,-alias_list,$(SRCDIR)/alias.list"
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/lc-note/kern-ver-str/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ C_SOURCES := main.c
all: a.out create-empty-corefile

create-empty-corefile:
$(MAKE) -f $(MAKEFILE_RULES) EXE=create-empty-corefile \
"$(MAKE)" -f $(MAKEFILE_RULES) EXE=create-empty-corefile \
CXX=$(CC) CXX_SOURCES=create-empty-corefile.cpp

include Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ create-empty-corefile:
CXX_SOURCES=create-multibin-corefile.cpp

libone.dylib: one.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=one DYLIB_C_SOURCES=one.c

libtwo.dylib: two.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=two DYLIB_C_SOURCES=two.c

include Makefile.rules
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/macCatalystAppMacOSFramework/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ override CC=xcrun clang
all: libfoo.dylib a.out

libfoo.dylib: foo.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=foo DYLIB_C_SOURCES=foo.c

include Makefile.rules
4 changes: 2 additions & 2 deletions lldb/test/API/macosx/skinny-corefile/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ include Makefile.rules
a.out: libto-be-removed libpresent

libto-be-removed: libpresent
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=to-be-removed.c DYLIB_NAME=to-be-removed \
LD_EXTRAS="-L. -lpresent"

libpresent:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=present.c DYLIB_NAME=present
2 changes: 1 addition & 1 deletion lldb/test/API/tools/lldb-dap/breakpoint/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ main-copy.cpp: main.cpp

# The following shared library will be used to test breakpoints under dynamic loading
libother: other-copy.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=other-copy.c DYLIB_NAME=other
3 changes: 3 additions & 0 deletions lldb/test/API/tools/lldb-dap/send-event/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
C_SOURCES := main.c

include Makefile.rules
67 changes: 67 additions & 0 deletions lldb/test/API/tools/lldb-dap/send-event/TestDAP_sendEvent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
Test lldb-dap send-event integration.
"""

import json

from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
import lldbdap_testcase


class TestDAP_sendEvent(lldbdap_testcase.DAPTestCaseBase):
def test_send_event(self):
"""
Test sending a custom event.
"""
program = self.getBuildArtifact("a.out")
source = "main.c"
custom_event_body = {
"key": 321,
"arr": [True],
}
self.build_and_launch(
program,
stopCommands=[
"lldb-dap send-event my-custom-event-no-body",
"lldb-dap send-event my-custom-event '{}'".format(
json.dumps(custom_event_body)
),
],
)

breakpoint_line = line_number(source, "// breakpoint")

self.set_source_breakpoints(source, [breakpoint_line])
self.continue_to_next_stop()

custom_event = self.dap_server.wait_for_event(
filter=["my-custom-event-no-body"]
)
self.assertEquals(custom_event["event"], "my-custom-event-no-body")
self.assertIsNone(custom_event.get("body", None))

custom_event = self.dap_server.wait_for_event(filter=["my-custom-event"])
self.assertEquals(custom_event["event"], "my-custom-event")
self.assertEquals(custom_event["body"], custom_event_body)

def test_send_internal_event(self):
"""
Test sending an internal event produces an error.
"""
program = self.getBuildArtifact("a.out")
source = "main.c"
self.build_and_launch(program)

breakpoint_line = line_number(source, "// breakpoint")

self.set_source_breakpoints(source, [breakpoint_line])
self.continue_to_next_stop()

resp = self.dap_server.request_evaluate(
"`lldb-dap send-event stopped", context="repl"
)
self.assertRegex(
resp["body"]["result"],
r"Invalid use of lldb-dap send-event, event \"stopped\" should be handled by lldb-dap internally.",
)
6 changes: 6 additions & 0 deletions lldb/test/API/tools/lldb-dap/send-event/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <stdio.h>

int main(int argc, char const *argv[]) {
printf("example\n"); // breakpoint 1
return 0;
}
4 changes: 2 additions & 2 deletions lldb/test/API/tools/lldb-server/libraries-svr4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ a.out: svr4lib_a svr4lib_b_quote
include Makefile.rules

svr4lib_a:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_NAME=svr4lib_a DYLIB_CXX_SOURCES=svr4lib_a.cpp \
DYLIB_ONLY=YES

svr4lib_b_quote:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_NAME=svr4lib_b\\\" DYLIB_CXX_SOURCES=svr4lib_b_quote.cpp \
DYLIB_ONLY=YES
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// XFAIL: *

// RUN: %clangxx_host -gdwarf -o %t %s
// RUN: %clang --target=x86_64-apple-macosx -c -gdwarf -o %t %s
// RUN: %lldb %t \
// RUN: -o "expr alignof(OverlappingFields)" \
// RUN: -o "expr sizeof(OverlappingFields)" \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// XFAIL: *

// RUN: %clangxx_host -gdwarf -o %t %s
// RUN: %clang --target=x86_64-apple-macosx -c -gdwarf -o %t %s
// RUN: %lldb %t \
// RUN: -o "expr alignof(OverlappingDerived)" \
// RUN: -o "expr sizeof(OverlappingDerived)" \
Expand Down
16 changes: 3 additions & 13 deletions lldb/tools/debugserver/source/RNBRemote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,6 @@ void append_hexified_string(std::ostream &ostrm, const std::string &string) {
}
}

extern void ASLLogCallback(void *baton, uint32_t flags, const char *format,
va_list args);

// from System.framework/Versions/B/PrivateHeaders/sys/codesign.h
extern "C" {
#define CS_OPS_STATUS 0 /* return status */
Expand Down Expand Up @@ -1773,8 +1770,6 @@ static std::string get_value(std::string &line) {

extern void FileLogCallback(void *baton, uint32_t flags, const char *format,
va_list args);
extern void ASLLogCallback(void *baton, uint32_t flags, const char *format,
va_list args);

rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) {
const char *c = p + strlen("qRcmd,");
Expand Down Expand Up @@ -1809,8 +1804,8 @@ rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) {
static_cast<uint32_t>(strtoul(value.c_str(), &end, 0));
if (errno == 0 && end && *end == '\0') {
DNBLogSetLogMask(logmask);
if (!DNBLogGetLogCallback())
DNBLogSetLogCallback(ASLLogCallback, NULL);
if (auto log_callback = OsLogger::GetLogFunction())
DNBLogSetLogCallback(log_callback, nullptr);
return SendPacket("OK");
}
errno = 0;
Expand Down Expand Up @@ -2177,13 +2172,8 @@ rnb_err_t set_logging(const char *p) {
// Enable DNB logging.
// Use the existing log callback if one was already configured.
if (!DNBLogGetLogCallback()) {
// Use the os_log()-based logger if available; otherwise,
// fallback to ASL.
auto log_callback = OsLogger::GetLogFunction();
if (log_callback)
if (auto log_callback = OsLogger::GetLogFunction())
DNBLogSetLogCallback(log_callback, nullptr);
else
DNBLogSetLogCallback(ASLLogCallback, nullptr);
}

// Update logging to use the configured log channel bitmask.
Expand Down
8 changes: 0 additions & 8 deletions lldb/tools/debugserver/source/libdebugserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,13 +311,6 @@ RNBRunLoopMode RNBRunLoopInferiorExecuting(RNBRemoteSP &remote) {
return mode;
}

void ASLLogCallback(void *baton, uint32_t flags, const char *format,
va_list args) {
#if 0
vprintf(format, args);
#endif
}

extern "C" int debug_server_main(int fd) {
#if 1
g_isatty = 0;
Expand All @@ -327,7 +320,6 @@ extern "C" int debug_server_main(int fd) {
DNBLogSetDebug(1);
DNBLogSetVerbose(1);
DNBLogSetLogMask(-1);
DNBLogSetLogCallback(ASLLogCallback, NULL);
#endif

signal(SIGPIPE, signal_handler);
Expand Down
62 changes: 62 additions & 0 deletions lldb/tools/lldb-dap/DAP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,68 @@ bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger,
return true;
}

// Sends a DAP event with an optional body.
//
// See
// https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent
bool SendEventRequestHandler::DoExecute(lldb::SBDebugger debugger,
char **command,
lldb::SBCommandReturnObject &result) {
// Command format like: `send-event <name> <body>?`
if (!command || !command[0] || llvm::StringRef(command[0]).empty()) {
result.SetError("Not enough arguments found, expected format "
"`lldb-dap send-event <name> <body>?`.");
return false;
}

llvm::StringRef name{command[0]};
// Events that are stateful and should be handled by lldb-dap internally.
const std::array internal_events{"breakpoint", "capabilities", "continued",
"exited", "initialize", "loadedSource",
"module", "process", "stopped",
"terminated", "thread"};
if (std::find(internal_events.begin(), internal_events.end(), name) !=
std::end(internal_events)) {
std::string msg =
llvm::formatv("Invalid use of lldb-dap send-event, event \"{0}\" "
"should be handled by lldb-dap internally.",
name)
.str();
result.SetError(msg.c_str());
return false;
}

llvm::json::Object event(CreateEventObject(name));

if (command[1] && !llvm::StringRef(command[1]).empty()) {
// See if we have unused arguments.
if (command[2]) {
result.SetError(
"Additional arguments found, expected `lldb-dap send-event "
"<name> <body>?`.");
return false;
}

llvm::StringRef raw_body{command[1]};

llvm::Expected<llvm::json::Value> body = llvm::json::parse(raw_body);

if (!body) {
llvm::Error err = body.takeError();
std::string msg = "Failed to parse custom event body: " +
llvm::toString(std::move(err));
result.SetError(msg.c_str());
return false;
}

event.try_emplace("body", std::move(*body));
}

g_dap.SendJSON(llvm::json::Value(std::move(event)));
result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
return true;
}

void DAP::SetFrameFormat(llvm::StringRef format) {
if (format.empty())
return;
Expand Down
5 changes: 5 additions & 0 deletions lldb/tools/lldb-dap/DAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ struct ReplModeRequestHandler : public lldb::SBCommandPluginInterface {
lldb::SBCommandReturnObject &result) override;
};

struct SendEventRequestHandler : public lldb::SBCommandPluginInterface {
bool DoExecute(lldb::SBDebugger debugger, char **command,
lldb::SBCommandReturnObject &result) override;
};

struct DAP {
std::string debug_adaptor_path;
InputStream input;
Expand Down
31 changes: 31 additions & 0 deletions lldb/tools/lldb-dap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,37 @@ The initial repl-mode can be configured with the cli flag `--repl-mode=<mode>`
and may also be adjusted at runtime using the lldb command
`lldb-dap repl-mode <mode>`.

#### `lldb-dap send-event`

lldb-dap includes a command to trigger a Debug Adapter Protocol event
from a script.

The event maybe a custom DAP event or a standard event, if the event is not
handled internally by `lldb-dap`.

This command has the format:

```
lldb-dap send-event <name> <body>?
```

For example you can use a launch configuration hook to trigger custom events like:

```json
{
"program": "exe",
"stopCommands": [
"lldb-dap send-event MyStopEvent",
"lldb-dap send-event MyStopEvent '{\"key\": 321}",
]
}
```

[See the specification](https://microsoft.github.io/debug-adapter-protocol/specification#Base_Protocol_Event)
for more details on Debug Adapter Protocol events and the VS Code
[debug.onDidReceiveDebugSessionCustomEvent](https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent)
API for handling a custom event from an extension.

## Contributing

`lldb-dap` and `lldb` are developed under the umbrella of the [LLVM project](https://llvm.org/).
Expand Down
2 changes: 2 additions & 0 deletions lldb/tools/lldb-dap/lldb-dap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1896,6 +1896,8 @@ void request_initialize(const llvm::json::Object &request) {
cmd.AddCommand(
"repl-mode", new ReplModeRequestHandler(),
"Get or set the repl behavior of lldb-dap evaluation requests.");
cmd.AddCommand("send-event", new SendEventRequestHandler(),
"Sends an DAP event to the client.");

g_dap.progress_event_thread = std::thread(ProgressEventThreadFunction);

Expand Down
55 changes: 53 additions & 2 deletions lldb/unittests/Utility/DiagnosticsRenderingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,63 @@ std::string Render(std::vector<DiagnosticDetail> details) {
} // namespace

TEST_F(ErrorDisplayTest, RenderStatus) {
DiagnosticDetail::SourceLocation inline_loc;
inline_loc.in_user_input = true;
using SourceLocation = DiagnosticDetail::SourceLocation;
{
SourceLocation inline_loc;
inline_loc.in_user_input = true;
std::string result =
Render({DiagnosticDetail{inline_loc, eSeverityError, "foo", ""}});
ASSERT_TRUE(StringRef(result).contains("error:"));
ASSERT_TRUE(StringRef(result).contains("foo"));
}

{
// Test that diagnostics on the same column can be handled and all
// three errors are diagnosed.
SourceLocation loc1 = {FileSpec{"a.c"}, 13, 11, 0, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 13, 13, 0, false, true};
std::string result =
Render({DiagnosticDetail{loc1, eSeverityError, "1", "1"},
DiagnosticDetail{loc1, eSeverityError, "2", "2"},
DiagnosticDetail{loc2, eSeverityError, "3", "3"}});
ASSERT_TRUE(StringRef(result).contains("error: 1"));
ASSERT_TRUE(StringRef(result).contains("error: 2"));
ASSERT_TRUE(StringRef(result).contains("error: 3"));
}
{
// Test that diagnostics in reverse order are emitted correctly.
SourceLocation loc1 = {FileSpec{"a.c"}, 1, 20, 0, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 2, 10, 0, false, true};
std::string result =
Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"},
DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}});
ASSERT_LT(StringRef(result).find("Y"), StringRef(result).find("X"));
}
{
// Test that diagnostics in reverse order are emitted correctly.
SourceLocation loc1 = {FileSpec{"a.c"}, 2, 10, 0, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 1, 20, 0, false, true};
std::string result =
Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"},
DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}});
ASSERT_LT(StringRef(result).find("Y"), StringRef(result).find("X"));
}
{
// Test that range diagnostics are emitted correctly.
SourceLocation loc1 = {FileSpec{"a.c"}, 1, 1, 3, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 1, 5, 3, false, true};
std::string result =
Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"},
DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}});
auto lines = StringRef(result).split('\n');
auto line1 = lines.first;
lines = lines.second.split('\n');
auto line2 = lines.first;
lines = lines.second.split('\n');
auto line3 = lines.first;
// 1234567
ASSERT_EQ(line1, "^~~ ^~~");
ASSERT_EQ(line2, "| error: Y");
ASSERT_EQ(line3, "error: X");
}
}
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/BasicTTIImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1998,6 +1998,9 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
case Intrinsic::atan:
ISD = ISD::FATAN;
break;
case Intrinsic::atan2:
ISD = ISD::FATAN2;
break;
case Intrinsic::sinh:
ISD = ISD::FSINH;
break;
Expand Down
24 changes: 24 additions & 0 deletions llvm/include/llvm/CodeGen/EarlyIfConversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===- llvm/CodeGen/EarlyIfConversion.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 LLVM_CODEGEN_EARLYIFCONVERSION_H
#define LLVM_CODEGEN_EARLYIFCONVERSION_H

#include "llvm/CodeGen/MachinePassManager.h"

namespace llvm {

class EarlyIfConverterPass : public PassInfoMixin<EarlyIfConverterPass> {
public:
PreservedAnalyses run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM);
};

} // namespace llvm

#endif // LLVM_CODEGEN_EARLYIFCONVERSION_H
37 changes: 35 additions & 2 deletions llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,11 +599,22 @@ class LegalizeRuleSet {
LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
return actionFor(LegalizeAction::Legal, Types);
}
LegalizeRuleSet &legalFor(bool Pred, std::initializer_list<LLT> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Legal, Types);
}
/// The instruction is legal when type indexes 0 and 1 is any type pair in the
/// given list.
LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
return actionFor(LegalizeAction::Legal, Types);
}
LegalizeRuleSet &legalFor(bool Pred,
std::initializer_list<std::pair<LLT, LLT>> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Legal, Types);
}
/// The instruction is legal when type index 0 is any type in the given list
/// and imm index 0 is anything.
LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) {
Expand Down Expand Up @@ -749,6 +760,12 @@ class LegalizeRuleSet {
return actionFor(LegalizeAction::Libcall, Types);
}
LegalizeRuleSet &
libcallFor(bool Pred, std::initializer_list<std::pair<LLT, LLT>> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Libcall, Types);
}
LegalizeRuleSet &
libcallForCartesianProduct(std::initializer_list<LLT> Types) {
return actionForCartesianProduct(LegalizeAction::Libcall, Types);
}
Expand Down Expand Up @@ -846,12 +863,23 @@ class LegalizeRuleSet {
LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
return actionFor(LegalizeAction::Custom, Types);
}
LegalizeRuleSet &customFor(bool Pred, std::initializer_list<LLT> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Custom, Types);
}

/// The instruction is custom when type indexes 0 and 1 is any type pair in the
/// given list.
/// The instruction is custom when type indexes 0 and 1 is any type pair in
/// the given list.
LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
return actionFor(LegalizeAction::Custom, Types);
}
LegalizeRuleSet &customFor(bool Pred,
std::initializer_list<std::pair<LLT, LLT>> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Custom, Types);
}

LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
return actionForCartesianProduct(LegalizeAction::Custom, Types);
Expand Down Expand Up @@ -990,6 +1018,11 @@ class LegalizeRuleSet {
scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()),
changeTo(typeIdx(TypeIdx), Ty));
}
LegalizeRuleSet &minScalar(bool Pred, unsigned TypeIdx, const LLT Ty) {
if (!Pred)
return *this;
return minScalar(TypeIdx, Ty);
}

/// Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet &minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/ISDOpcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ enum NodeType {
STRICT_FASIN,
STRICT_FACOS,
STRICT_FATAN,
STRICT_FATAN2,
STRICT_FSINH,
STRICT_FCOSH,
STRICT_FTANH,
Expand Down Expand Up @@ -994,6 +995,8 @@ enum NodeType {
FPOWI,
/// FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
FLDEXP,
/// FATAN2 - atan2, inspired by libm.
FATAN2,

/// FFREXP - frexp, extract fractional and exponent component of a
/// floating-point value. Returns the two components as separate return
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/MIRParser/MIParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct VRegInfo {
} D;
Register VReg;
Register PreferredReg;
std::vector<uint8_t> Flags;
uint8_t Flags = 0;
};

using Name2RegClassMap = StringMap<const TargetRegisterClass *>;
Expand Down
Loading