Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mis-aligned access issues with s390x #4702

Merged
merged 1 commit into from
Aug 16, 2022

Conversation

uweigand
Copy link
Member

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.

FYI @cfallin @bjorn3 - this is the last missing cranelift patch to make cg_clif work on s390x.

@github-actions github-actions bot added cranelift Issues related to the Cranelift code generator cranelift:module labels Aug 12, 2022
@@ -342,22 +342,18 @@ impl Module for ObjectModule {
}
*defined = true;

let align = std::cmp::max(self.function_alignment, self.isa.symbol_alignment());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should default function_alignment to isa.symbol_alignment().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't do that because it seemed that would allow a caller to override the function alignment to smaller than isa.symbol_alignment(), and that simply doesn't work on s390x.

Copy link
Member

@cfallin cfallin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks generally good; one suggestion for clarity below.

@@ -21,6 +21,7 @@ pub fn mem_finalize(
have_d12: bool,
have_d20: bool,
have_pcrel: bool,
have_unaligned_pcrel: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This list of flags is long enough now that it's starting to feel a bit error-prone; and e.g. the diff adding false in the right places is hard to review carefully. Could we turn this into a struct of flags?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, that makes sense. Like this?

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.
Copy link
Member

@cfallin cfallin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@cfallin cfallin merged commit a916788 into bytecodealliance:main Aug 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:module cranelift Issues related to the Cranelift code generator
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants