Skip to content

Comments

X86 64 abi misaligned packed#16667

Open
kojix2 wants to merge 4 commits intocrystal-lang:masterfrom
kojix2:x86_64-abi-misaligned-packed
Open

X86 64 abi misaligned packed#16667
kojix2 wants to merge 4 commits intocrystal-lang:masterfrom
kojix2:x86_64-abi-misaligned-packed

Conversation

@kojix2
Copy link
Contributor

@kojix2 kojix2 commented Feb 23, 2026

Hello. While reading Crystal source code on Raptor Mini, Raptor pointed out a possible bug, so I tried to fix it. I don't fully understand the issue, but since I'm submitting this PR, not Raptor, I'll explain it.

Packed structs are not always naturally aligned and may contain misaligned fields. In the x86_64 ABI, such values should be passed indirectly through memory, not through registers, in Crystal::ABI::X86_64#classify. This PR fixes an incorrect slot range that was used when setting the Memory class for this case.

Also updated has_misaligned_fields? to correctly handle nested structs and arrays. It now passes the offset through recursive calls to check all fields properly.

@[Link(ldflags: "-L#{__DIR__} -lfoo")]
lib LibX
  @[Packed]
  struct Inner
    x : UInt16
    y : UInt8
  end

  struct Outer
    a : UInt8
    b : Inner
  end

  fun foo(x : Outer) : Int32
end

x = LibX::Outer.new
x.a = 1_u8
x.b.x = 2_u16
x.b.y = 3_u8

pp sizeof(LibX::Inner)
pp sizeof(LibX::Outer)
pp LibX.foo(x)
#include <stdint.h>

#pragma pack(push, 1)
struct Inner {
  uint16_t x;
  uint8_t y;
};
#pragma pack(pop)

struct Outer {
  uint8_t a;
  struct Inner b;
};

int foo(struct Outer x) {
  return (int)x.a + (int)x.b.x + (int)x.b.y;
}
gcc -fPIC -shared -o libfoo.so foo.c

Before

Index out of bounds (IndexError)
  from /crystal/src/indexable.cr:1002:11 in 'unify'
  from /crystal/src/compiler/crystal/codegen/abi/x86_64.cr:120:13 in 'classify'
  from /crystal/src/compiler/crystal/codegen/abi/x86_64.cr:155:20 in 'classify'
  from /crystal/src/compiler/crystal/codegen/abi/x86_64.cr:155:20 in 'classify'
  from /crystal/src/llvm/type.cr:34:5 in 'classify'
  from /crystal/src/compiler/crystal/codegen/abi/x86_64.cr:88:21 in 'abi_info'
  from /crystal/src/compiler/crystal/codegen/call.cr:149:7 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2581:9 in 'codegen_assign'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/enumerable.cr:510:7 in '??'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2550:7 in 'codegen'
  from /crystal/src/compiler/crystal/compiler.cr:236:15 in 'compile'
  from /crystal/src/compiler/crystal/command.cr:340:5 in 'run'
  from /crystal/src/compiler/crystal/command.cr:55:3 in '__crystal_main'
  from /crystal/src/crystal/main.cr:129:5 in 'main'
  from /crystal/src/crystal/system/unix/main.cr:10:3 in 'main'
  from src/env/__libc_start_main.c:95:2 in 'libc_start_main_stage2'
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues

After

3
4
6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant