Fix mis-aligned access issues with s390x (#4702)
This fixes two problems: minimum symbol alignment for the LARL instruction, and alignment requirements for LRL/LGRL etc. The first problem is that the LARL instruction used to load a symbol address (PC relative) requires that the target symbol is at least 2-byte aligned. This is always guaranteed for code symbols (all instructions must be 2-aligned anyway), but not necessarily for data symbols. Other s390x compilers fix this problem by ensuring that all global symbols are always emitted with a minimum 2-byte alignment. This patch introduces an equivalent mechanism for cranelift: - Add a symbol_alignment routine to TargetIsa, similar to the existing code_section_alignment routine. - Respect symbol_alignment as minimum alignment for all symbols emitted in the object backend (code and data). The second problem is that PC-relative instructions that directly *access* data (like LRL/LGRL, STRL/STGRL etc.) not only have the 2-byte requirement like LARL, but actually require that their memory operand is *naturally* aligned (i.e. alignment is at least the size of the access). This property (natural alignment for memory accesses) is supposed to be provided by the "aligned" flag in MemFlags; however, this is not implemented correctly at the moment. To fix this, this patch: - Only emits PC-relative memory access instructions if the "aligned" flag is set in the associated MemFlags. - Fixes a bug in emit_small_memory_copy and emit_small_memset which currently set the aligned flag unconditionally, ignoring the actual alignment info passed by their caller. Tested with wasmtime and cg_clif.
This commit is contained in:
@@ -816,7 +816,9 @@ impl<'a> FunctionBuilder<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
flags.set_aligned();
|
||||
if u64::from(src_align) >= access_size && u64::from(dest_align) >= access_size {
|
||||
flags.set_aligned();
|
||||
}
|
||||
|
||||
// Load all of the memory first. This is necessary in case `dest` overlaps.
|
||||
// It can also improve performance a bit.
|
||||
@@ -903,7 +905,9 @@ impl<'a> FunctionBuilder<'a> {
|
||||
let size = self.ins().iconst(config.pointer_type(), size as i64);
|
||||
self.call_memset(config, buffer, ch, size);
|
||||
} else {
|
||||
flags.set_aligned();
|
||||
if u64::from(buffer_align) >= access_size {
|
||||
flags.set_aligned();
|
||||
}
|
||||
|
||||
let ch = u64::from(ch);
|
||||
let raw_value = if int_type == types::I64 {
|
||||
|
||||
Reference in New Issue
Block a user