On some 32-bit architectures, we were violating memory alignment
requirements for double-precision floats, in cell fields and on det and
nondet stacks. Bug #299.
We now only take the address of a double field when it occurs on an
aligned memory address, i.e. when it starts at an even word offset from
the start of a cell (this assumption is incompatible with term-size
profiling which adds a hidden word before the start of the cell).
For the det stack, we can round up allocations to keep the stack pointer
double-aligned, then allocate slots for doubles at even word offsets
from the stack pointer.
It would be trickier for the nondet stack. Multiple frame types exist
on the nondet stack, and the different frame types are identified by
their sizes: 3-word and 4-word temporary frames, and 5/6+ word ordinary
frames. Rather than rounding up frame sizes to even numbers of words,
we would probably want to dynamically pad ordinary frame allocations,
such that any doubles in the frame will be at aligned addresses.
However, in this change, we simply store box floats on the nondet stack.
compiler/globals.m:
Add predicate which returns whether double-width floats
should be stored on the det stack.
compiler/handle_options.m:
Disable double-word fields in term-size profiling grades.
compiler/code_info.m:
Add a predicate to round up det stack frame sizes.
Remember the width of floats stored on the det stack in
exprn_opts.
compiler/hlds_llds.m:
compiler/llds.m:
compiler/stack_layout.m:
Delete the possibility of double-width slots on the nondet
stack.
Remember det_stack_float_width in exprn_opts.
compiler/llds_out_data.m:
Add wrapper macro `MR_dword_ptr' when taking the address of a
double.
Only take the address of doubles on the det stack.
compiler/llds_out_instr.m:
compiler/llds_out_util.m:
Only assign a double field in a single C statement when it is
aligned.
Assert that the stack pointer is incremented by an even number,
if necessary.
compiler/mlds_to_c.m:
Only take the address of doubles when aligned.
compiler/middle_rec.m:
compiler/proc_gen.m:
Round up det stack frame allocations to even numbers of words
when necessary.
compiler/stack_alloc.m:
Add padding as required so that double-word variables will
be allocated at even-word offsets from the stack pointer.
compiler/opt_debug.m:
compiler/par_conj_gen.m:
Conform to changes.
runtime/mercury_conf_param.h:
runtime/mercury_float.h:
Add macro `MR_dword_ptr' to be wrapped around instances where
the address of a double is taken. When `MR_DEBUG_DWORD_ALIGNMENT'
is defined (and using gcc or clang) the address is checked to be
properly aligned. Almost all our development is done on x86 or
x86-64 architecture which do not have strict memory alignment
requirements, making violations hard to check otherwise.
runtime/mercury_deconstruct.c:
runtime/mercury_layout_util.c:
Use `MR_float_from_dword' over `MR_float_from_dword_ptr' as the
former does not require dword alignment.
Related fix: looking up `double' variables on the nondet stack
used the stack pointer for the det stack instead. Fix it,
though the code now won't be executed after this change.
tests/debugger/nondet_stack.exp5:
Add new expected output. This is the same as nondet_stack.exp
except that det stack frames have been rounded up.
Estimated hours taken: 0.5
Branches: main
runtime/mercury_context.c:
Reverted a change that moved the initial position of MR_ctxt_sp by
one word.
tests/debugger/nondet_stack.exp5:
Removed as this is no longer required.
Estimated hours taken: 0.1
Branches: main
tests/debugger/nondet_stack.exp5:
Add expected output for lowlevel grades following a change to the
initialisation of the det stack pointer. This output is the same as
nondet_stack.exp except that the det stack pointers are decreased by
one word.