Summary: If a platform removes some builtin implementations (e.g. via the Darwin-excludes mechanism) then this can lead to test failures because the test expects an implementation to be available. To solve this lit features are added for each configuration based on which sources are included in the builtin library. The features are of the form `librt_has_<name>` where `<name>` is the name of the source file with the file extension removed. This handles C and assembly sources. With the lit features in place it is possible to make certain tests require them. Example: ``` REQUIRES: librt_has_comparedf2 ``` All top-level tests in `test/builtins/Unit` (i.e. not under `arm`, `ppc`, and `riscv`) have been annotated with the appropriate `REQUIRES: librt_has_*` statement. rdar://problem/55520987 Reviewers: beanz, steven_wu, arphaman, dexonsmith, phosek, thakis Subscribers: mgorny, #sanitizers, llvm-commits Tags: #llvm, #sanitizers Differential Revision: https://reviews.llvm.org/D68064 llvm-svn: 375150
377 lines
7.6 KiB
C
377 lines
7.6 KiB
C
// RUN: %clang_builtins %s %librt -o %t && %run %t
|
|
// REQUIRES: librt_has_multc3
|
|
//===-- multc3_test.c - Test __multc3 -------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file tests __multc3 for the compiler_rt library.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include <stdio.h>
|
|
|
|
#if _ARCH_PPC || __aarch64__
|
|
|
|
#include "int_lib.h"
|
|
#include <math.h>
|
|
#include <complex.h>
|
|
|
|
// Returns: the product of a + ib and c + id
|
|
|
|
COMPILER_RT_ABI long double _Complex
|
|
__multc3(long double __a, long double __b, long double __c, long double __d);
|
|
|
|
enum {zero, non_zero, inf, NaN, non_zero_nan};
|
|
|
|
int
|
|
classify(long double _Complex x)
|
|
{
|
|
if (x == 0)
|
|
return zero;
|
|
if (isinf(creall(x)) || isinf(cimagl(x)))
|
|
return inf;
|
|
if (isnan(creall(x)) && isnan(cimagl(x)))
|
|
return NaN;
|
|
if (isnan(creall(x)))
|
|
{
|
|
if (cimagl(x) == 0)
|
|
return NaN;
|
|
return non_zero_nan;
|
|
}
|
|
if (isnan(cimagl(x)))
|
|
{
|
|
if (creall(x) == 0)
|
|
return NaN;
|
|
return non_zero_nan;
|
|
}
|
|
return non_zero;
|
|
}
|
|
|
|
int test__multc3(long double a, long double b, long double c, long double d)
|
|
{
|
|
long double _Complex r = __multc3(a, b, c, d);
|
|
// printf("test__multc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n",
|
|
// a, b, c, d, creall(r), cimagl(r));
|
|
long double _Complex dividend;
|
|
long double _Complex divisor;
|
|
|
|
__real__ dividend = a;
|
|
__imag__ dividend = b;
|
|
__real__ divisor = c;
|
|
__imag__ divisor = d;
|
|
|
|
switch (classify(dividend))
|
|
{
|
|
case zero:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != zero)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != zero)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case non_zero:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != zero)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != non_zero)
|
|
return 1;
|
|
if (r != a * c - b * d + _Complex_I*(a * d + b * c))
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case inf:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case NaN:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case non_zero_nan:
|
|
switch (classify(divisor))
|
|
{
|
|
case zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case inf:
|
|
if (classify(r) != inf)
|
|
return 1;
|
|
break;
|
|
case NaN:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
case non_zero_nan:
|
|
if (classify(r) != NaN)
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
long double x[][2] =
|
|
{
|
|
{ 1.e-6, 1.e-6},
|
|
{-1.e-6, 1.e-6},
|
|
{-1.e-6, -1.e-6},
|
|
{ 1.e-6, -1.e-6},
|
|
|
|
{ 1.e+6, 1.e-6},
|
|
{-1.e+6, 1.e-6},
|
|
{-1.e+6, -1.e-6},
|
|
{ 1.e+6, -1.e-6},
|
|
|
|
{ 1.e-6, 1.e+6},
|
|
{-1.e-6, 1.e+6},
|
|
{-1.e-6, -1.e+6},
|
|
{ 1.e-6, -1.e+6},
|
|
|
|
{ 1.e+6, 1.e+6},
|
|
{-1.e+6, 1.e+6},
|
|
{-1.e+6, -1.e+6},
|
|
{ 1.e+6, -1.e+6},
|
|
|
|
{NAN, NAN},
|
|
{-INFINITY, NAN},
|
|
{-2, NAN},
|
|
{-1, NAN},
|
|
{-0.5, NAN},
|
|
{-0., NAN},
|
|
{+0., NAN},
|
|
{0.5, NAN},
|
|
{1, NAN},
|
|
{2, NAN},
|
|
{INFINITY, NAN},
|
|
|
|
{NAN, -INFINITY},
|
|
{-INFINITY, -INFINITY},
|
|
{-2, -INFINITY},
|
|
{-1, -INFINITY},
|
|
{-0.5, -INFINITY},
|
|
{-0., -INFINITY},
|
|
{+0., -INFINITY},
|
|
{0.5, -INFINITY},
|
|
{1, -INFINITY},
|
|
{2, -INFINITY},
|
|
{INFINITY, -INFINITY},
|
|
|
|
{NAN, -2},
|
|
{-INFINITY, -2},
|
|
{-2, -2},
|
|
{-1, -2},
|
|
{-0.5, -2},
|
|
{-0., -2},
|
|
{+0., -2},
|
|
{0.5, -2},
|
|
{1, -2},
|
|
{2, -2},
|
|
{INFINITY, -2},
|
|
|
|
{NAN, -1},
|
|
{-INFINITY, -1},
|
|
{-2, -1},
|
|
{-1, -1},
|
|
{-0.5, -1},
|
|
{-0., -1},
|
|
{+0., -1},
|
|
{0.5, -1},
|
|
{1, -1},
|
|
{2, -1},
|
|
{INFINITY, -1},
|
|
|
|
{NAN, -0.5},
|
|
{-INFINITY, -0.5},
|
|
{-2, -0.5},
|
|
{-1, -0.5},
|
|
{-0.5, -0.5},
|
|
{-0., -0.5},
|
|
{+0., -0.5},
|
|
{0.5, -0.5},
|
|
{1, -0.5},
|
|
{2, -0.5},
|
|
{INFINITY, -0.5},
|
|
|
|
{NAN, -0.},
|
|
{-INFINITY, -0.},
|
|
{-2, -0.},
|
|
{-1, -0.},
|
|
{-0.5, -0.},
|
|
{-0., -0.},
|
|
{+0., -0.},
|
|
{0.5, -0.},
|
|
{1, -0.},
|
|
{2, -0.},
|
|
{INFINITY, -0.},
|
|
|
|
{NAN, 0.},
|
|
{-INFINITY, 0.},
|
|
{-2, 0.},
|
|
{-1, 0.},
|
|
{-0.5, 0.},
|
|
{-0., 0.},
|
|
{+0., 0.},
|
|
{0.5, 0.},
|
|
{1, 0.},
|
|
{2, 0.},
|
|
{INFINITY, 0.},
|
|
|
|
{NAN, 0.5},
|
|
{-INFINITY, 0.5},
|
|
{-2, 0.5},
|
|
{-1, 0.5},
|
|
{-0.5, 0.5},
|
|
{-0., 0.5},
|
|
{+0., 0.5},
|
|
{0.5, 0.5},
|
|
{1, 0.5},
|
|
{2, 0.5},
|
|
{INFINITY, 0.5},
|
|
|
|
{NAN, 1},
|
|
{-INFINITY, 1},
|
|
{-2, 1},
|
|
{-1, 1},
|
|
{-0.5, 1},
|
|
{-0., 1},
|
|
{+0., 1},
|
|
{0.5, 1},
|
|
{1, 1},
|
|
{2, 1},
|
|
{INFINITY, 1},
|
|
|
|
{NAN, 2},
|
|
{-INFINITY, 2},
|
|
{-2, 2},
|
|
{-1, 2},
|
|
{-0.5, 2},
|
|
{-0., 2},
|
|
{+0., 2},
|
|
{0.5, 2},
|
|
{1, 2},
|
|
{2, 2},
|
|
{INFINITY, 2},
|
|
|
|
{NAN, INFINITY},
|
|
{-INFINITY, INFINITY},
|
|
{-2, INFINITY},
|
|
{-1, INFINITY},
|
|
{-0.5, INFINITY},
|
|
{-0., INFINITY},
|
|
{+0., INFINITY},
|
|
{0.5, INFINITY},
|
|
{1, INFINITY},
|
|
{2, INFINITY},
|
|
{INFINITY, INFINITY}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int main()
|
|
{
|
|
#if _ARCH_PPC || __aarch64__
|
|
const unsigned N = sizeof(x) / sizeof(x[0]);
|
|
unsigned i, j;
|
|
for (i = 0; i < N; ++i)
|
|
{
|
|
for (j = 0; j < N; ++j)
|
|
{
|
|
if (test__multc3(x[i][0], x[i][1], x[j][0], x[j][1]))
|
|
return 1;
|
|
}
|
|
}
|
|
#else
|
|
printf("skipped\n");
|
|
#endif
|
|
return 0;
|
|
}
|