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:
@@ -348,22 +348,18 @@ impl Module for ObjectModule {
|
||||
}
|
||||
*defined = true;
|
||||
|
||||
let align = std::cmp::max(self.function_alignment, self.isa.symbol_alignment());
|
||||
let (section, offset) = if self.per_function_section {
|
||||
let symbol_name = self.object.symbol(symbol).name.clone();
|
||||
let (section, offset) = self.object.add_subsection(
|
||||
StandardSection::Text,
|
||||
&symbol_name,
|
||||
bytes,
|
||||
self.function_alignment,
|
||||
);
|
||||
let (section, offset) =
|
||||
self.object
|
||||
.add_subsection(StandardSection::Text, &symbol_name, bytes, align);
|
||||
self.object.symbol_mut(symbol).section = SymbolSection::Section(section);
|
||||
self.object.symbol_mut(symbol).value = offset;
|
||||
(section, offset)
|
||||
} else {
|
||||
let section = self.object.section_id(StandardSection::Text);
|
||||
let offset =
|
||||
self.object
|
||||
.add_symbol_data(symbol, section, bytes, self.function_alignment);
|
||||
let offset = self.object.add_symbol_data(symbol, section, bytes, align);
|
||||
(section, offset)
|
||||
};
|
||||
|
||||
@@ -452,7 +448,7 @@ impl Module for ObjectModule {
|
||||
)
|
||||
};
|
||||
|
||||
let align = align.unwrap_or(1);
|
||||
let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
|
||||
let offset = match *init {
|
||||
Init::Uninitialized => {
|
||||
panic!("data is not initialized yet");
|
||||
|
||||
Reference in New Issue
Block a user