Skip to content

Commit

Permalink
Merge branch 'topic/vadim/32bit' into 'master'
Browse files Browse the repository at this point in the history
Support 32bit platforms

See merge request eng/ide/VSS!328
  • Loading branch information
godunko committed Jun 28, 2024
2 parents b837935 + bf12c1c commit 4793470
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 67 deletions.
5 changes: 4 additions & 1 deletion alire.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "vss"
description = "Advanced string and text manipulation with Unicode support"
version = "22.0.0-20210830"
version = "25.0.0-dev"
tags = ["unicode", "json", "text"]

authors = ["AdaCore"]
Expand All @@ -15,5 +15,8 @@ project-files = ["gnat/vss_text.gpr", "gnat/vss_json.gpr"]
generate_ada = false
generate_c = false

[configuration.variables]
Max_Supported_Integer_Size = {type = "Enum", values = ["128", "64"], default = "128"}

[build-switches]
"*".ada_version = "Ada2022"
6 changes: 5 additions & 1 deletion config/vss_config.gpr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--
-- Copyright (C) 2020-2023, AdaCore
-- Copyright (C) 2020-2024, AdaCore
--
-- SPDX-License-Identifier: Apache-2.0
--
Expand Down Expand Up @@ -106,6 +106,10 @@ abstract project Vss_Config is
,"-gnat2012" -- Ada 2012 Mode, see comment.
);

type Max_Supported_Integer_Size_Kind is ("128", "64");
Max_Supported_Integer_Size : Max_Supported_Integer_Size_Kind :=
external ("VSS_MAX_SUPPORTED_INTEGER_SIZE", "128");

type Build_Profile_Kind is ("release", "validation", "development");
Build_Profile : Build_Profile_Kind :=
external ("VSS_BUILD_PROFILE", external ("BUILD_PROFILE", "development"));
Expand Down
8 changes: 7 additions & 1 deletion gnat/vss_json.gpr
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
--
-- Copyright (C) 2020-2023, AdaCore
-- Copyright (C) 2020-2024, AdaCore
--
-- SPDX-License-Identifier: Apache-2.0
--

-- VSS: JSON processing subproject

with "../config/vss_config";
with "vss_common";
with "vss_text";

Expand Down Expand Up @@ -33,4 +34,9 @@ project VSS_JSON is

package Linker renames VSS_Common.Linker;

package Naming is
for Implementation ("VSS.JSON.Implementation.Arithmetic_64")
use "vss-json-implementation-arithmetic_64__" & Vss_Config.Max_Supported_Integer_Size & ".adb";
end Naming;

end VSS_JSON;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
--
-- Copyright (C) 2024, AdaCore
--
-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--

-- Multiply and Multiply_Add opertations on Integer_64 that returns
-- unpacked Integer_128 result and can be implemented in hardware.

with Interfaces;

package VSS.JSON.Implementation.Arithmetic_64
with Preelaborate
is

procedure Multiply
(A : Interfaces.Unsigned_64;
B : Interfaces.Unsigned_64;
L : out Interfaces.Unsigned_64;
H : out Interfaces.Unsigned_64) with Inline;
-- Multiplication of two 64-bit unsigned integers into 128-bit values,
-- splitted into high and low 64-bit unsigned integers. On x86_64 it is
-- optimized into single instruction.

procedure Multiply_Add
(Left : Interfaces.Unsigned_64;
Right : Interfaces.Unsigned_64;
Result : out Interfaces.Unsigned_64;
Overflow : in out Interfaces.Unsigned_64) with Inline;
-- Multiplication of two 64-bit unsigned integers into 128-bit values,
-- add of carry. Result is splitted into high and low 64-bit unsigned
-- integers. On x86_64 it is optimized into few instructions.

end VSS.JSON.Implementation.Arithmetic_64;
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
--
-- Copyright (C) 2024, AdaCore
--
-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--

pragma Ada_2022;

package body VSS.JSON.Implementation.Arithmetic_64
with Preelaborate
is

--------------
-- Multiply --
--------------

procedure Multiply
(A : Interfaces.Unsigned_64;
B : Interfaces.Unsigned_64;
L : out Interfaces.Unsigned_64;
H : out Interfaces.Unsigned_64)
is
use type Interfaces.Unsigned_128;

R : constant Interfaces.Unsigned_128 :=
Interfaces.Unsigned_128 (A) * Interfaces.Unsigned_128 (B);

begin
L := Interfaces.Unsigned_64 (R mod 2 ** 64);
H := Interfaces.Unsigned_64 (R / 2 ** 64);
end Multiply;

------------------
-- Multiply_Add --
------------------

procedure Multiply_Add
(Left : Interfaces.Unsigned_64;
Right : Interfaces.Unsigned_64;
Result : out Interfaces.Unsigned_64;
Overflow : in out Interfaces.Unsigned_64)
is
use type Interfaces.Unsigned_128;

R : constant Interfaces.Unsigned_128 :=
Interfaces.Unsigned_128 (Left) * Interfaces.Unsigned_128 (Right)
+ Interfaces.Unsigned_128 (Overflow);

begin
Result := Interfaces.Unsigned_64 (R mod 2 ** 64);
Overflow := Interfaces.Unsigned_64 (R / 2 ** 64);
end Multiply_Add;

end VSS.JSON.Implementation.Arithmetic_64;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
--
-- Copyright (C) 2024, AdaCore
--
-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--

pragma Ada_2022;

package body VSS.JSON.Implementation.Arithmetic_64
with Preelaborate
is

--------------
-- Multiply --
--------------

procedure Multiply
(A : Interfaces.Unsigned_64;
B : Interfaces.Unsigned_64;
L : out Interfaces.Unsigned_64;
H : out Interfaces.Unsigned_64)
is
use type Interfaces.Unsigned_64;

AL : constant Interfaces.Unsigned_64 := A and 16#FFFF_FFFF#;
AH : constant Interfaces.Unsigned_64 := Interfaces.Shift_Right (A, 32);
BL : constant Interfaces.Unsigned_64 := B and 16#FFFF_FFFF#;
BH : constant Interfaces.Unsigned_64 := Interfaces.Shift_Right (B, 32);

U : constant Interfaces.Unsigned_64 := AL * BL;
T : constant Interfaces.Unsigned_64 :=
AH * BL + Interfaces.Shift_Right (U, 32);
TL : constant Interfaces.Unsigned_64 := T and 16#FFFF_FFFF#;
W1 : constant Interfaces.Unsigned_64 := TL + AL * BH;
W2 : constant Interfaces.Unsigned_64 := Interfaces.Shift_Right (T, 32);

begin
L := A * B;
H := AH * BH + W2 + Interfaces.Shift_Right (W1, 32);
end Multiply;

------------------
-- Multiply_Add --
------------------

procedure Multiply_Add
(Left : Interfaces.Unsigned_64;
Right : Interfaces.Unsigned_64;
Result : out Interfaces.Unsigned_64;
Overflow : in out Interfaces.Unsigned_64)
is
use type Interfaces.Unsigned_64;

C : constant Interfaces.Unsigned_64 := Overflow;
L : Interfaces.Unsigned_64;

begin
Multiply (Left, Right, L, Overflow);

Result := L + C;

if Result < L or Result < C then
Overflow := @ + 1;
end if;
end Multiply_Add;

end VSS.JSON.Implementation.Arithmetic_64;
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
--
-- Copyright (C) 2022-2023, AdaCore
-- Copyright (C) 2022-2024, AdaCore
--
-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--

pragma Ada_2022;

with VSS.JSON.Implementation.Arithmetic_64;

package body VSS.JSON.Implementation.Big_Integers is

use type Interfaces.Unsigned_64;
Expand All @@ -17,15 +19,6 @@ package body VSS.JSON.Implementation.Big_Integers is
Overflow : out Interfaces.Unsigned_64);
-- Add of two 64-bit unsigned integers. Return result and overflow.

procedure Scalar_Multiply
(Left : Interfaces.Unsigned_64;
Right : Interfaces.Unsigned_64;
Result : out Interfaces.Unsigned_64;
Overflow : in out Interfaces.Unsigned_64);
-- Multiplication of two 64-bit unsigned integers into 128-bit values,
-- add of carry. Result is splitted into high and low 64-bit unsigned
-- integers. On x86_64 it is optimized into few instructions.

procedure Add
(Self : in out Big_Integer;
Value : Interfaces.Unsigned_64;
Expand Down Expand Up @@ -262,7 +255,8 @@ package body VSS.JSON.Implementation.Big_Integers is

begin
for J in Self.Data'First .. Self.Last loop
Scalar_Multiply (Self.Data (J), Value, Self.Data (J), Carry);
VSS.JSON.Implementation.Arithmetic_64.Multiply_Add
(Self.Data (J), Value, Self.Data (J), Carry);
end loop;

if Carry /= 0 then
Expand Down Expand Up @@ -451,27 +445,6 @@ package body VSS.JSON.Implementation.Big_Integers is
Overflow := (if Add (Left, Right, Result'Access) then 1 else 0);
end Scalar_Add;

---------------------
-- Scalar_Multiply --
---------------------

procedure Scalar_Multiply
(Left : Interfaces.Unsigned_64;
Right : Interfaces.Unsigned_64;
Result : out Interfaces.Unsigned_64;
Overflow : in out Interfaces.Unsigned_64)
is
use type Interfaces.Unsigned_128;

R : constant Interfaces.Unsigned_128 :=
Interfaces.Unsigned_128 (Left) * Interfaces.Unsigned_128 (Right)
+ Interfaces.Unsigned_128 (Overflow);

begin
Result := Interfaces.Unsigned_64 (R mod 2 ** 64);
Overflow := Interfaces.Unsigned_64 (R / 2 ** 64);
end Scalar_Multiply;

---------
-- Set --
---------
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--
-- Copyright (C) 2022-2023, AdaCore
-- Copyright (C) 2022-2024, AdaCore
--
-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--
Expand All @@ -8,6 +8,7 @@ pragma Ada_2022;

with Ada.Unchecked_Conversion;

with VSS.JSON.Implementation.Arithmetic_64;
with VSS.JSON.Implementation.Numbers.Tables;

package body VSS.JSON.Implementation.Numbers.Eisel_Lemire is
Expand All @@ -31,15 +32,6 @@ package body VSS.JSON.Implementation.Numbers.Eisel_Lemire is
Convention => Intrinsic,
External_Name => "__builtin_clzll";

procedure Multiply
(A : Interfaces.Unsigned_64;
B : Interfaces.Unsigned_64;
L : out Interfaces.Unsigned_64;
H : out Interfaces.Unsigned_64);
-- Multiplication of two 64-bit unsigned integers into 128-bit values,
-- splitted into high and low 64-bit unsigned integers. On x86_64 it is
-- optimized into single instruction.

procedure Compute_Product_Approximation
(W : Interfaces.Unsigned_64;
Q : Interfaces.Integer_32;
Expand Down Expand Up @@ -164,7 +156,8 @@ package body VSS.JSON.Implementation.Numbers.Eisel_Lemire is
-- For small values of q, e.g., q in [0,27], the answer is always exact
-- because the first call of Multiply gives the exact answer.

Multiply (W, Tables.Powers_Of_Five (Q).L, FL, FH);
VSS.JSON.Implementation.Arithmetic_64.Multiply
(W, Tables.Powers_Of_Five (Q).L, FL, FH);

if (FH and Precision_Mask) = Precision_Mask then
-- could further guard with (lower + w < lower)
Expand All @@ -173,7 +166,8 @@ package body VSS.JSON.Implementation.Numbers.Eisel_Lemire is
-- expectation is that the compiler will optimize this extra
-- work away if needed.

Multiply (W, Tables.Powers_Of_Five (Q).H, SL, SH);
VSS.JSON.Implementation.Arithmetic_64.Multiply
(W, Tables.Powers_Of_Five (Q).H, SL, SH);
FL := @ + SH;

if SH > FL then
Expand Down Expand Up @@ -560,26 +554,6 @@ package body VSS.JSON.Implementation.Numbers.Eisel_Lemire is
Number.Power := @ - 1;
end Halfway;

--------------
-- Multiply --
--------------

procedure Multiply
(A : Interfaces.Unsigned_64;
B : Interfaces.Unsigned_64;
L : out Interfaces.Unsigned_64;
H : out Interfaces.Unsigned_64)
is
use type Interfaces.Unsigned_128;

R : constant Interfaces.Unsigned_128 :=
Interfaces.Unsigned_128 (A) * Interfaces.Unsigned_128 (B);

begin
L := Interfaces.Unsigned_64 (R mod 2 ** 64);
H := Interfaces.Unsigned_64 (R / 2 ** 64);
end Multiply;

--------------------
-- Scale_Negative --
--------------------
Expand Down

0 comments on commit 4793470

Please sign in to comment.