From: Siva Chandra Reddy Date: Fri, 17 Sep 2021 04:38:17 +0000 (+0000) Subject: [libc] Add implementations of div, ldiv, lldiv and imaxdiv. X-Git-Tag: upstream/15.0.7~31126 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=74670e79b0a00224c04dfc6a446ea4439f4cfca4;p=platform%2Fupstream%2Fllvm.git [libc] Add implementations of div, ldiv, lldiv and imaxdiv. Reviewed By: michaelrj Differential Revision: https://reviews.llvm.org/D109952 --- diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 8dbbb64..20583ea 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -46,13 +46,20 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strtok_r # inttypes.h entrypoints + libc.src.inttypes.imaxdiv libc.src.inttypes.strtoimax libc.src.inttypes.strtoumax # stdlib.h entrypoints + libc.src.stdlib.abs libc.src.stdlib.atoi libc.src.stdlib.atol libc.src.stdlib.atoll + libc.src.stdlib.div + libc.src.stdlib.labs + libc.src.stdlib.ldiv + libc.src.stdlib.llabs + libc.src.stdlib.lldiv libc.src.stdlib.strtol libc.src.stdlib.strtoll libc.src.stdlib.strtoul @@ -161,15 +168,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.truncl ) -if(LLVM_LIBC_FULL_BUILD) - list(APPEND TARGET_LIBC_ENTRYPOINTS - # stdlib.h entrypoints - libc.src.stdlib.abs - libc.src.stdlib.labs - libc.src.stdlib.llabs - ) -endif() - set(TARGET_LLVMLIBC_ENTRYPOINTS ${TARGET_LIBC_ENTRYPOINTS} ${TARGET_LIBM_ENTRYPOINTS} diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td index ddcf901..757469b 100644 --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -111,6 +111,21 @@ def AssertAPI : PublicAPI<"assert.h"> { def CTypeAPI : PublicAPI<"ctype.h"> { } +def IMaxDivT : TypeDecl<"imaxdiv_t"> { + let Decl = [{ + typedef struct { + intmax_t quot; + intmax_t rem; + } imaxdiv_t; + }]; +} + +def IntTypesAPI : PublicAPI<"inttypes.h"> { + let TypeDeclarations = [ + IMaxDivT, + ]; +} + def MathErrHandlingMacro : MacroDef<"math_errhandling"> { let Defn = [{ #ifndef math_errhandling @@ -239,7 +254,39 @@ def StdIOAPI : PublicAPI<"stdio.h"> { ]; } +def DivT : TypeDecl<"div_t"> { + let Decl = [{ + typedef struct { + int quot; + int rem; + } div_t; + }]; +} + +def LDivT : TypeDecl<"ldiv_t"> { + let Decl = [{ + typedef struct { + long quot; + long rem; + } ldiv_t; + }]; +} + +def LLDivT : TypeDecl<"lldiv_t"> { + let Decl = [{ + typedef struct { + long long quot; + long long rem; + } lldiv_t; + }]; +} + def StdlibAPI : PublicAPI<"stdlib.h"> { + let TypeDeclarations = [ + DivT, + LDivT, + LLDivT, + ]; } def TimeAPI : PublicAPI<"time.h"> { diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 9836d62..503bd9a 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -46,13 +46,20 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strtok_r # inttypes.h entrypoints + libc.src.inttypes.imaxdiv libc.src.inttypes.strtoimax libc.src.inttypes.strtoumax # stdlib.h entrypoints + libc.src.stdlib.abs libc.src.stdlib.atoi libc.src.stdlib.atol libc.src.stdlib.atoll + libc.src.stdlib.div + libc.src.stdlib.labs + libc.src.stdlib.ldiv + libc.src.stdlib.llabs + libc.src.stdlib.lldiv libc.src.stdlib.strtol libc.src.stdlib.strtoll libc.src.stdlib.strtoul @@ -172,9 +179,6 @@ if(LLVM_LIBC_FULL_BUILD) # stdlib.h entrypoints libc.src.stdlib._Exit libc.src.stdlib.abort - libc.src.stdlib.abs - libc.src.stdlib.labs - libc.src.stdlib.llabs # signal.h entrypoints libc.src.signal.raise diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index c50f917..46f56a4 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -7,6 +7,10 @@ def StdC : StandardSpec<"stdc"> { PtrType StructTmPtr = PtrType; PtrType TimeTTypePtr = PtrType; + NamedType DivTType = NamedType<"div_t">; + NamedType LDivTType = NamedType<"ldiv_t">; + NamedType LLDivTType = NamedType<"lldiv_t">; + HeaderSpec Assert = HeaderSpec< "assert.h", [ @@ -471,32 +475,48 @@ def StdC : StandardSpec<"stdc"> { HeaderSpec StdLib = HeaderSpec< "stdlib.h", [], // Macros - [], // Types + [ + DivTType, + LDivTType, + LLDivTType, + ], // Types [], // Enumerations [ FunctionSpec<"abort", RetValSpec, [ArgSpec]>, + FunctionSpec<"abs", RetValSpec, [ArgSpec]>, + FunctionSpec<"labs", RetValSpec, [ArgSpec]>, + FunctionSpec<"llabs", RetValSpec, [ArgSpec]>, + FunctionSpec<"atoi", RetValSpec, [ArgSpec]>, FunctionSpec<"atol", RetValSpec, [ArgSpec]>, FunctionSpec<"atoll", RetValSpec, [ArgSpec]>, - FunctionSpec<"labs", RetValSpec, [ArgSpec]>, - FunctionSpec<"llabs", RetValSpec, [ArgSpec]>, + + FunctionSpec<"div", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"ldiv", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"lldiv", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"strtol", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoll", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoul", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoull", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"_Exit", RetValSpec, [ArgSpec]>, ] >; + NamedType IMaxDivTType = NamedType<"imaxdiv_t">; + HeaderSpec IntTypes = HeaderSpec< "inttypes.h", [], // Macros - [], // Types + [ + IMaxDivTType, + ], // Types [], // Enumerations [ FunctionSpec<"imaxabs", RetValSpec, [ArgSpec]>, - FunctionSpec<"imaxdiv", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"imaxdiv", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"strtoimax", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoumax", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, ] diff --git a/libc/src/__support/integer_operations.h b/libc/src/__support/integer_operations.h index 4c13bb8..c27a263 100644 --- a/libc/src/__support/integer_operations.h +++ b/libc/src/__support/integer_operations.h @@ -19,6 +19,13 @@ integerAbs(T n) { return (n < 0) ? -n : n; } +template +static constexpr cpp::EnableIfType::Value, void> +integerRemQuo(T x, T y, T ", T &rem) { + quot = x / y; + rem = x % y; +} + } // namespace __llvm_libc #endif // LLVM_LIBC_SRC_STDLIB_ABS_UTILS_H diff --git a/libc/src/inttypes/CMakeLists.txt b/libc/src/inttypes/CMakeLists.txt index 65c1d7e..81068bd 100644 --- a/libc/src/inttypes/CMakeLists.txt +++ b/libc/src/inttypes/CMakeLists.txt @@ -17,3 +17,13 @@ add_entrypoint_object( DEPENDS libc.src.__support.str_conv_utils ) + +add_entrypoint_object( + imaxdiv + SRCS + imaxdiv.cpp + HDRS + imaxdiv.h + DEPENDS + libc.src.__support.integer_operations +) diff --git a/libc/src/inttypes/imaxdiv.cpp b/libc/src/inttypes/imaxdiv.cpp new file mode 100644 index 0000000..6189fc1 --- /dev/null +++ b/libc/src/inttypes/imaxdiv.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of imaxdiv -----------------------------------------===// +// +// 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/inttypes/imaxdiv.h" +#include "src/__support/common.h" +#include "src/__support/integer_operations.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(imaxdiv_t, imaxdiv, (intmax_t x, intmax_t y)) { + imaxdiv_t res; + integerRemQuo(x, y, res.quot, res.rem); + return res; +} + +} // namespace __llvm_libc diff --git a/libc/src/inttypes/imaxdiv.h b/libc/src/inttypes/imaxdiv.h new file mode 100644 index 0000000..c8af352 --- /dev/null +++ b/libc/src/inttypes/imaxdiv.h @@ -0,0 +1,20 @@ +//===-- Implementation header for imaxdiv -----------------------*- 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_INTTYPES_IMAXDIV_H +#define LLVM_LIBC_SRC_INTTYPES_IMAXDIV_H + +#include + +namespace __llvm_libc { + +imaxdiv_t imaxdiv(intmax_t x, intmax_t y); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_INTTYPES_IMAXDIV_H diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt index bf1b637..4f67612 100644 --- a/libc/src/stdlib/CMakeLists.txt +++ b/libc/src/stdlib/CMakeLists.txt @@ -124,3 +124,33 @@ add_entrypoint_object( DEPENDS libc.src.__support.integer_operations ) + +add_entrypoint_object( + div + SRCS + div.cpp + HDRS + div.h + DEPENDS + libc.src.__support.integer_operations +) + +add_entrypoint_object( + ldiv + SRCS + ldiv.cpp + HDRS + ldiv.h + DEPENDS + libc.src.__support.integer_operations +) + +add_entrypoint_object( + lldiv + SRCS + lldiv.cpp + HDRS + lldiv.h + DEPENDS + libc.src.__support.integer_operations +) diff --git a/libc/src/stdlib/div.cpp b/libc/src/stdlib/div.cpp new file mode 100644 index 0000000..042346d --- /dev/null +++ b/libc/src/stdlib/div.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of div ---------------------------------------------===// +// +// 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/stdlib/div.h" +#include "src/__support/common.h" +#include "src/__support/integer_operations.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(div_t, div, (int x, int y)) { + div_t res; + integerRemQuo(x, y, res.quot, res.rem); + return res; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdlib/div.h b/libc/src/stdlib/div.h new file mode 100644 index 0000000..ec1ded7 --- /dev/null +++ b/libc/src/stdlib/div.h @@ -0,0 +1,20 @@ +//===-- Implementation header for div ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +#ifndef LLVM_LIBC_SRC_STDLIB_DIV_H +#define LLVM_LIBC_SRC_STDLIB_DIV_H + +namespace __llvm_libc { + +div_t div(int x, int y); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_DIV_H diff --git a/libc/src/stdlib/ldiv.cpp b/libc/src/stdlib/ldiv.cpp new file mode 100644 index 0000000..fdac260 --- /dev/null +++ b/libc/src/stdlib/ldiv.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of ldiv --------------------------------------------===// +// +// 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/stdlib/ldiv.h" +#include "src/__support/common.h" +#include "src/__support/integer_operations.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(ldiv_t, ldiv, (long x, long y)) { + ldiv_t res; + integerRemQuo(x, y, res.quot, res.rem); + return res; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdlib/ldiv.h b/libc/src/stdlib/ldiv.h new file mode 100644 index 0000000..f4e7730 --- /dev/null +++ b/libc/src/stdlib/ldiv.h @@ -0,0 +1,20 @@ +//===-- Implementation header for ldiv --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +#ifndef LLVM_LIBC_SRC_STDLIB_LDIV_H +#define LLVM_LIBC_SRC_STDLIB_LDIV_H + +namespace __llvm_libc { + +ldiv_t ldiv(long x, long y); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_LDIV_H diff --git a/libc/src/stdlib/lldiv.cpp b/libc/src/stdlib/lldiv.cpp new file mode 100644 index 0000000..958b01f --- /dev/null +++ b/libc/src/stdlib/lldiv.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of lldiv -------------------------------------------===// +// +// 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/stdlib/lldiv.h" +#include "src/__support/common.h" +#include "src/__support/integer_operations.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(lldiv_t, lldiv, (long long x, long long y)) { + lldiv_t res; + integerRemQuo(x, y, res.quot, res.rem); + return res; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdlib/lldiv.h b/libc/src/stdlib/lldiv.h new file mode 100644 index 0000000..7f0de5c --- /dev/null +++ b/libc/src/stdlib/lldiv.h @@ -0,0 +1,20 @@ +//===-- Implementation header for lldiv -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +#ifndef LLVM_LIBC_SRC_STDLIB_LLDIV_H +#define LLVM_LIBC_SRC_STDLIB_LLDIV_H + +namespace __llvm_libc { + +lldiv_t lldiv(long long x, long long y); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_LDIV_H diff --git a/libc/test/src/inttypes/CMakeLists.txt b/libc/test/src/inttypes/CMakeLists.txt index d9885ba5..9a6d6ac 100644 --- a/libc/test/src/inttypes/CMakeLists.txt +++ b/libc/test/src/inttypes/CMakeLists.txt @@ -19,3 +19,16 @@ add_libc_unittest( DEPENDS libc.src.inttypes.strtoumax ) + +add_libc_unittest( + imaxdiv_test + SUITE + libc_inttypes_unittests + SRCS + imaxdiv_test.cpp + HDRS + ../stdlib/DivTest.h + DEPENDS + libc.include.stdlib + libc.src.inttypes.imaxdiv +) diff --git a/libc/test/src/inttypes/imaxdiv_test.cpp b/libc/test/src/inttypes/imaxdiv_test.cpp new file mode 100644 index 0000000..321aad5 --- /dev/null +++ b/libc/test/src/inttypes/imaxdiv_test.cpp @@ -0,0 +1,15 @@ +//===-- Unittests for imaxdiv ---------------------------------------------===// +// +// 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 "../stdlib/DivTest.h" + +#include "src/inttypes/imaxdiv.h" + +#include + +LIST_DIV_TESTS(intmax_t, imaxdiv_t, __llvm_libc::imaxdiv) diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt index 6aed171..4eb8526 100644 --- a/libc/test/src/stdlib/CMakeLists.txt +++ b/libc/test/src/stdlib/CMakeLists.txt @@ -128,3 +128,42 @@ add_libc_unittest( DEPENDS libc.src.stdlib.llabs ) + +add_libc_unittest( + div_test + SUITE + libc_stdlib_unittests + SRCS + div_test.cpp + HDRS + DivTest.h + DEPENDS + libc.include.stdlib + libc.src.stdlib.div +) + +add_libc_unittest( + ldiv_test + SUITE + libc_stdlib_unittests + SRCS + ldiv_test.cpp + HDRS + DivTest.h + DEPENDS + libc.include.stdlib + libc.src.stdlib.ldiv +) + +add_libc_unittest( + lldiv_test + SUITE + libc_stdlib_unittests + SRCS + lldiv_test.cpp + HDRS + DivTest.h + DEPENDS + libc.include.stdlib + libc.src.stdlib.lldiv +) diff --git a/libc/test/src/stdlib/DivTest.h b/libc/test/src/stdlib/DivTest.h new file mode 100644 index 0000000..13978ac --- /dev/null +++ b/libc/test/src/stdlib/DivTest.h @@ -0,0 +1,37 @@ +//===-- A template class for testing div functions --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "utils/UnitTest/Test.h" + +template +class DivTest : public __llvm_libc::testing::Test { +public: + using DivFunc = ReturnType(IntType, IntType); + + void simpleTest(DivFunc func) { + auto result = func(10, 3); + EXPECT_EQ(result.quot, IntType(3)); + EXPECT_EQ(result.rem, IntType(1)); + + result = func(-10, 3); + EXPECT_EQ(result.quot, IntType(-3)); + EXPECT_EQ(result.rem, IntType(-1)); + + result = func(-10, -3); + EXPECT_EQ(result.quot, IntType(3)); + EXPECT_EQ(result.rem, IntType(-1)); + + result = func(10, -3); + EXPECT_EQ(result.quot, IntType(-3)); + EXPECT_EQ(result.rem, IntType(1)); + } +}; + +#define LIST_DIV_TESTS(IntType, ReturnType, func) \ + using LlvmLibcDivTest = DivTest; \ + TEST_F(LlvmLibcDivTest, SimpleTest) { simpleTest(func); } diff --git a/libc/test/src/stdlib/div_test.cpp b/libc/test/src/stdlib/div_test.cpp new file mode 100644 index 0000000..6b1f20d --- /dev/null +++ b/libc/test/src/stdlib/div_test.cpp @@ -0,0 +1,15 @@ +//===-- Unittests for div -------------------------------------------------===// +// +// 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 "DivTest.h" + +#include "src/stdlib/div.h" + +#include + +LIST_DIV_TESTS(int, div_t, __llvm_libc::div) diff --git a/libc/test/src/stdlib/ldiv_test.cpp b/libc/test/src/stdlib/ldiv_test.cpp new file mode 100644 index 0000000..d28d387 --- /dev/null +++ b/libc/test/src/stdlib/ldiv_test.cpp @@ -0,0 +1,15 @@ +//===-- Unittests for ldiv ------------------------------------------------===// +// +// 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 "DivTest.h" + +#include "src/stdlib/ldiv.h" + +#include + +LIST_DIV_TESTS(long, ldiv_t, __llvm_libc::ldiv) diff --git a/libc/test/src/stdlib/lldiv_test.cpp b/libc/test/src/stdlib/lldiv_test.cpp new file mode 100644 index 0000000..5fa0de2 --- /dev/null +++ b/libc/test/src/stdlib/lldiv_test.cpp @@ -0,0 +1,15 @@ +//===-- Unittests for lldiv -----------------------------------------------===// +// +// 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 "DivTest.h" + +#include "src/stdlib/lldiv.h" + +#include + +LIST_DIV_TESTS(long long, lldiv_t, __llvm_libc::lldiv)