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

arm32 homogeneous aggregates ABI issues #3626

Open
IllusionMan1212 opened this issue May 24, 2024 · 1 comment
Open

arm32 homogeneous aggregates ABI issues #3626

IllusionMan1212 opened this issue May 24, 2024 · 1 comment

Comments

@IllusionMan1212
Copy link
Contributor

Context

  • Operating System & Odin Version:
        Odin:    dev-2024-05:e1c4b9b06
        OS:      Debian GNU/Linux 12 (bookworm), Linux 6.1.0-21-armmp-lpae
        CPU:     ARM
        RAM:     992 MiB
        Backend: LLVM 14.0.6

Expected Behavior

Correct values are passed to, and returned from, foreign functions.

Current Behavior

Argument values are incorrect when printed in foreign functions and return values are incorrect when printed on the odin-side.

Failure Information (for bugs)

The Odin compiler is currently not conforming to the arm32 ABI homogeneous aggregates section.

There are 3 issues that need fixing:

  • Homogeneous aggregates passed as an argument where the aggregate doesn't exceed 4 elements.
  • Homogeneous aggregates returned from a procedure where the aggregate doesn't exceed 4 elements.
  • Homogeneous aggregates passed as an argument where the aggregate EXCEEDS 4 elements.

For the first and the second points, the same issue was happening on arm64 and was reported in #2561 and fixed by f3a4630 .
I've confirmed that same code fixes 1 and 2 but 3 still happens, I haven't been able to test to see if it's an issue on arm64 too but I suspect it is.

Steps to Reproduce

Simple C code compiled with gcc -c -o main.o main.c and made into a static lib with ar rcs libodintest.a main.o

#include <stdio.h>

typedef struct Vector2 {
	float x;
	float y;
} Vector2;

typedef struct Camera2D {
	Vector2 offset;
	Vector2 target;
	float rotation;
	float zoom;
} Camera2D;

void homogenous_arg_test(Vector2 pos) {
	printf("homogenous_arg_test result: ");
	printf("Pos: {%f, %f}\n", pos.x, pos.y);
}

Vector2 homogenous_return_test() {
	printf("homogenous_return_test result: ");
	Vector2 pos = (Vector2){45, 90};
	printf("Returning {%f, %f}\n", pos.x, pos.y);
	return pos;
}

void homogenous_arg_more_than_4_members(Vector2 pos, Camera2D cam) {
	printf("homogenous_arg_more_than_4_members result: ");
	printf("Pos: {%f, %f}\n", pos.x, pos.y);
	printf("Camera Offset: {%f, %f}\n", cam.offset.x, cam.offset.y);
	printf("Camera Target: {%f, %f}\n", cam.target.x, cam.target.y);
	printf("Camera Rotation: %f\n", cam.rotation);
	printf("Camera Zoom: %f\n", cam.zoom);
}

And the odin code that calls the C library

package main

import "core:fmt"

foreign import ext "libodintest.a"

Vector2 :: [2]f32

Camera2D :: struct {
	offset: Vector2,
	target: Vector2,
	rotation: f32,
	zoom: f32,
}

foreign ext {
	homogenous_arg_test :: proc(pos: Vector2) ---
	homogenous_return_test :: proc() -> Vector2 ---
	homogenous_arg_more_than_4_members :: proc(pos: Vector2, cam: Camera2D) ---
}

main :: proc() {
	homogenous_arg_test({15, 30})

	ret := homogenous_return_test()
	fmt.println("Return on odin side is:", ret)

	cam := Camera2D{
		offset = {99, 100},
		target = {74, 43},
		rotation = 5.0,
		zoom = 3.0,
	}

	homogenous_arg_more_than_4_members({33, 66}, cam)
}

And this is what gets printed to the terminal

homogenous_arg_test result: Pos: {0.000000, 0.000000}
homogenous_return_test result: Returning {45.000000, 90.000000}
Return on odin side is: [0, 0]
homogenous_arg_more_than_4_members result: Pos: {17644434555492938809344.000000, 12710676290573701508590102118400.000000}
Camera Offset: {33.000000, 66.000000}
Camera Target: {99.000000, 100.000000}
Camera Rotation: 74.000000
Camera Zoom: 43.000000

Failure Logs

N/A

@gingerBill
Copy link
Member

The current ABI for arm32 is mostly a placeholder, and will need correcting for aggregates. The problem is reverse engineering how LLVM does things more than anything.

https://github.com/odin-lang/Odin/blob/master/src/llvm_abi.cpp#L1392-L1472

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

No branches or pull requests

2 participants