Comment the push int function

This commit is contained in:
Igor M 2024-03-11 13:20:08 +02:00
parent ce9ed30bac
commit b4701bb4d5

View file

@ -110,16 +110,44 @@ size_t label_lookup(LabelVec *labels, char *name, size_t len) {
return INVALID; return INVALID;
} }
// safety: assumes the buffer has enough place for specified integer size // safety: assumes the buffer has enough place for specified integer size.
// `sign` is a bitset, where bit `1` indicates that value accepts a signed int,
// and bit `2` indicates that value accepts an unsigned int.
AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) { AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) {
int valid_uint = val >> (size * 8) == 0; // Unsigned integers must have all upper bits set to zero. To check this,
// we shift the value right by the integer size and verify it equals zero.
int valid_uint = (val >> (size * 8)) == 0;
// For signed integers, the sign-extended high bits must match the sign bit.
// By shifting right by one less than the total bit size (size * 8 - 1),
// we isolate the sign bit and any sign-extended bits. For a value fitting
// in the signed range, this operation results in either 0 (for non-negative
// values) or -1 (for negative values due to sign extension).
int64_t int_shifted = ((int64_t)val) >> (size * 8 - 1); int64_t int_shifted = ((int64_t)val) >> (size * 8 - 1);
int valid_int = int_shifted == 0 || (~int_shifted) == 0;
// Note: this assumes the format for `sign` is a bitset. // To unify the check for both positive and negative cases, we adjust
// non-zero values (-1) by incrementing by 1. This turns -1 into 0,
// enabling a single check for 0 to validate both cases. This adjustment
// simplifies the validation logic, allowing us to use a single condition to
// check for proper sign extension or zero extension in the original value.
int_shifted += int_shifted != 0;
// A valid signed integer will have `int_shifted` equal to 0
// after adjustment, indicating proper sign extension.
int valid_int = int_shifted == 0;
// Validity bitmask to represents whether the value
// fits as signed, unsigned, or both.
int validity = valid_int | (valid_uint << 1); int validity = valid_int | (valid_uint << 1);
// If the value's validity doesn't match the `sign` requirements,
// we report an overflow.
if ((validity & sign) == 0) { if ((validity & sign) == 0) {
return ErrImmediateOverflow; return ErrImmediateOverflow;
} }
// Write out the bytes of the integer to the buffer in little-endian order,
// starting with the lowest byte first.
for (size_t ii = 0; ii < size; ii += 1) { for (size_t ii = 0; ii < size; ii += 1) {
buf[ii] = val & 0xff; buf[ii] = val & 0xff;
val >>= 8; val >>= 8;