Closed Robbepop closed 6 years ago
Commit 4a9948fc1f3f202202e504fdc5889ccf641caef5 added this new to_primitive
module and documentation and stubs for its entire API. The full implementation and tests are still required.
Design question:
How should ApInt::try_to_iN
and ApInt::truncate_to_iN
behave for any N
when the sign bit is 1
?
Should there be an implicit sign extension so that -1
will properly be casted into a -1
or will it be a simple reinterpretation of the digit's bits?
Answer
I answered this myself by looking at how Rust treats casts from e.g. i32
to i64
for negative numbers. Gladly it is also sign and value preserving, so a -27_i32
will be cast to -27_i64
which is what users want generally - and if not they might take the unsigned bridge.
A decent chunk of the functionality proposed by this issue was implemented in e7902aed7002727b595153e8ef896d952225e01c and 231aabb52a7bd4cb26b067bf428513388a9b14a5.
What needs to be done before this issue can be closed: Write tests for the new API.
To cover enough cases one needs to create tests over several different dimensions.
We need different input values (e.g. i64
values) and construct ApInt
instances of them for many different bit widths and then test all the different resize_to_*
and try_to_*
methods for them.
This is a lot of work that needs to be automated. One can not simply write so many direct assertions.
Also for resize_to_*
methods there needs to be a case distinction for ApInt
instances that have a greater than or less than bit width compared to the target resize bit width since they either truncate or sign-resize their original values.
Note: Here again the PrimitiveTy
utility may be of help.
Finished this task in commit 64402b4167aaa2270670706e068bf9219564ffd9.
ApInt
offers a lot of functionality to convert primitive data types such asu8
,i16
,u64
and eveni128
intoApInt
instances, however, there is no support for the other way around.The proposed API additions are the following:
The
truncate_to_*
methods will simply truncate theApInt
bits to the correct bit width and return the value. If theApInt
has a bit width smaller than the primitive type theApInt
s value is simply taken for conversion. This has the effect thatApInt
s with a bit width smaller than the primitive cannot represent a negative value. So a 1-bit bit widthApInt
with value1
will convert to1_u8
upon conversion tou8
.ApInt::resize_to_bool
ApInt::resize_to_u8
ApInt::resize_to_i8
ApInt::resize_to_u16
ApInt::resize_to_i16
ApInt::resize_to_u32
ApInt::resize_to_i32
ApInt::resize_to_u64
ApInt::resize_to_i64
ApInt::resize_to_u128
ApInt::resize_to_i128
The second proposed API tries to reinterpret the
ApInt
into the given primitive but won't truncate bits of it. Instead, if theApInt
instance requires a greater bit width for its value representation that what can be represented with the primitive data type anError
is returned instead.ApInt::try_to_bool
ApInt::try_to_u8
ApInt::try_to_i8
ApInt::try_to_u16
ApInt::try_to_i16
ApInt::try_to_u32
ApInt::try_to_i32
ApInt::try_to_u64
ApInt::try_to_i64
ApInt::try_to_u128
ApInt::try_to_i128
Unit tests for
ApInt::try_to_*
methodsApInt::resize_to_*
methods