Skip to content

PowerPC 32-bit: all aggregates passed indirectly, small structs should be coerced to integers #500

@SebTardif

Description

@SebTardif

Summary

On PowerPC 32-bit (Linux), ALL aggregates are passed indirectly via pointer, regardless of size. The SVR4 ABI requires small structs (8 bytes or less) to be passed by value in GPRs, coerced to integer types.

Location

compiler/rustc_target/src/callconv/powerpc.rs, line 28

Bug

if arg.layout.pass_indirectly_in_non_rustic_abis(cx) || arg.layout.is_aggregate() {
    arg.make_indirect();
}

ALL aggregates hit arg.make_indirect(). But the PowerPC 32-bit SVR4 ABI passes small structs by value:

  • Structs <= 4 bytes: coerced to i32, passed in a single GPR
  • Structs <= 8 bytes: coerced to i64, passed in a GPR pair

Clang's PPC32_SVR4_ABIInfo::classifyArgumentType implements this coercion.

Impact

When Rust's extern "C" fn(x: SmallStruct) calls a C function, Rust passes a pointer in r3 but C expects the struct value in r3(:r4). The callee reads the pointer as the struct value, causing data corruption.

PowerPC 32-bit Linux is a tier 3 target with limited FFI usage, but this is a genuine ABI violation.

Fix

For structs <= 8 bytes on PowerPC 32-bit SVR4 targets, coerce to integer register type instead of making indirect.

Spec

PowerPC SVR4 ABI Supplement, Chapter 3 -- "Structures and unions that fit in 1 or 2 general purpose registers are passed by value."

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-abiABI and calling conventionsI-wrongWrong result or data corruptionP-mediumMedium impact: affects specific usage patternsbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions