Comments (19)
Linux uses the SystemV ABI, there's a pdf for it here: https://people.freebsd.org/~obrien/amd64-elf-abi.pdf
In the Parameter Passing section it describes passing structs. It looks like if the struct >16 bytes it'll always be passed in memory (via a pointer), but otherwise can be put in registers based on the rules on page 16-17.
from odin.
System V AMD64 ABI is now correctly supported.
from odin.
vec4
doesn't work too:
#include <stdio.h>
struct vec4 { float x, y, z, w; };
void CFunction(struct vec4 x) {
printf("Received struct vec4: %f %f %f %f\n", x.x, x.y, x.z, x.w);
}
#foreign_system_library myfunc "myfunc";
vec4 :: struct #ordered { x, y, z, w: f32 }
CFunction :: proc(x: vec4) #foreign myfunc;
main :: proc() {
x: vec4;
x.x = 1;
x.y = 2;
x.z = 3;
x.w = 4;
CFunction(x);
}
Received struct vec4: 1.000000 0.000000 2.000000 0.000000
But vec8
all of a sudden works:
#include <stdio.h>
struct vec8 { float x0, y0, z0, w0,
x1, y1, z1, w1; };
void CFunction(struct vec8 x) {
printf("Received struct vec8: %f %f %f %f %f %f %f %f\n", x.x0, x.y0, x.z0, x.w0,
x.x1, x.y1, x.z1, x.w1);
}
#foreign_system_library myfunc "myfunc";
vec8 :: struct #ordered { x0, y0, z0, w0,
x1, y1, z1, w1: f32 }
CFunction :: proc(x: vec8) #foreign myfunc;
main :: proc() {
x: vec8;
x.x0 = 1;
x.y0 = 2;
x.z0 = 3;
x.w0 = 4;
x.x1 = 5;
x.y1 = 6;
x.z1 = 7;
x.w1 = 8;
CFunction(x);
}
Received struct vec8: 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000
from odin.
vec7
works too...
from odin.
vec6
works too...
from odin.
And vec5
works too. So it means 4 32-bit values and lower cause an issue, maybe it triggers some optimization Odin not aware of somewhere...
from odin.
x86 difference (compiled with -O0 -g
flags):
diff --git a/incorrect.txt b/correct.txt
index f254b47..b4e9251 100644
--- a/incorrect.txt
+++ b/correct.txt
@@ -114,20 +114,19 @@ Disassembly of section .text:
0000000000000620 <CFunction>:
#include <stdio.h>
-struct vec4 { float x0, y0, z0, w0; };
+struct vec4 { float x0, y0, z0, w0; char a; };
void CFunction(struct vec4 x) {
push rbp
mov rbp,rsp
sub rsp,0x
+ lea rax,[rbp+0x]
lea rdi,[rip+0x]
- movlps QWORD PTR [rbp-0x],xmm0
- movlps QWORD PTR [rbp-0x],xmm1
printf("Received struct vec4: %f %f %f %f\n", x.x0, x.y0, x.z0, x.w0);
- cvtss2sd xmm0,DWORD PTR [rbp-0x]
- cvtss2sd xmm1,DWORD PTR [rbp-0x]
- cvtss2sd xmm2,DWORD PTR [rbp-0x]
- cvtss2sd xmm3,DWORD PTR [rbp-0x]
+ cvtss2sd xmm0,DWORD PTR [rax]
+ cvtss2sd xmm1,DWORD PTR [rax+0x]
+ cvtss2sd xmm2,DWORD PTR [rax+0x]
+ cvtss2sd xmm3,DWORD PTR [rax+0x]
mov al,0x
call 500 <printf@plt>
mov DWORD PTR [rbp-0x],eax
from odin.
Might be an ABI issue? I think Odin only obeys windows x64 ABI atm.
from odin.
@ThisDrunkDane maybe! Can't test on Windows, don't know how to create a dll with cl
, not a Windows programmer... :)
from odin.
Compiling with cl.exe /D_USRDLL /D_WINDLL main.c /MT /link /DLL /OUT:myfunc.dll
#include <stdio.h>
struct vec3 { float x, y, z; };
__declspec(dllexport)
void CFunction(struct vec3 x) {
printf("Received struct vec3: %f %f %f\n", x.x, x.y, x.z);
}
produces a dll, but when I try to run the odin file with odin.exe run main.odin
myfunc.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x2C0
from odin.
λ dumpbin.exe /exports myfunc.dll
Microsoft (R) COFF/PE Dumper Version 12.00.31101.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file myfunc.dll
File Type: DLL
Section contains the following exports for myfunc.dll
00000000 characteristics
5905EDB1 time date stamp Sun Apr 30 16:59:13 2017
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00001000 CFunction
Summary
4000 .data
1000 .pdata
7000 .rdata
1000 .reloc
C000 .text
¯\_(ツ)_/¯
from odin.
Duh, I should've link to .lib
file, not .dll
:) Yep, it all works fine on Windows:
Received struct vec3: 1.000000 2.000000 3.000000
from odin.
This is an ABI problem on Linux. I do not know what Linux's ABI is. On Windows, I'm using this rule https://github.com/gingerBill/Odin/blob/1430ca30a3a0677fb395d2c5c190e86f02ed2b06/src/check_expr.c#L1060.
I have yet to figure out what Linux is because I personally am not support Linux.
from odin.
Assuming how LLVM IR "works", I would assume if the size <= 16, it will be passed by value, else it is passed by pointer. Is this the case even if the size is not a multiple of 2 (like with windows)?
from odin.
I'm not certain, but the pdf makes it sound like it's not limited to powers of two.
from odin.
If so, I'll just try that and see if this fixes @procedural's problem.
from odin.
Slightly rewritten example because #ordered no longer appears to be supported:
package abitest;
foreign import myfunc "libmyfunc.so";
@(default_calling_convention="c")
foreign myfunc {
CFunction :: proc(x: vec3) ---;
}
vec3 :: struct { x, y, z: f32 };
main :: proc() {
x: vec3;
x.x = 1;
x.y = 2;
x.z = 3;
CFunction(x);
}
Still seems to be broken.
$ odin run main.odin
Received struct vec3: 1.000000 0.000000 0.000000
from odin.
The calling convention was never properly supported on Linux and I will need to see if I can fix this. On Linux, that vec3
struct would be passed in two registers: "64-bit vector" and a single float.
from odin.
I came across this bug today as well while trying to use the odin-sdl2 library.
Edit: the bug popped up when trying to pass a Color struct which is 4 u8s.
from odin.
Related Issues (20)
- Duplicate case doesn't trigger an error when switching on struct value HOT 3
- `-no-crt` hello world does not compile because of thread local usage
- LLVM 13 does not seem to work anymore
- Fail compiling odin from git source HOT 2
- linux llvm18 not found (even though the lib is in the folder) HOT 2
- Compiler assertion failure in switch over a union pointer
- Stack overflow with invalid pointer parameter type
- Aliasing import with same name crashes compiler HOT 12
- Linux version of Odin 2024-08 looks for the wrong LLVM library file name HOT 2
- Compiler assert failure when aliasing a package and using it in the file scope of another file
- #force_inline Allowed When Passing In Procedure As Parameter HOT 1
- Casting in return disables the "unsafe slice of a local variable returned" error
- Issue in Linux with os.write_entire_file( ), sillently capping at exactly 1 GB. HOT 1
- `core:odin/parser` doesn't handle field tags for bitfields
- Disabled polymorphic procedure error for different parameter types
- OpenGL helpers.odin - Logging issue
- Compiler not erroring when modifying the elements of a @(rodata) array or slice HOT 2
- Compiler panic when passing bit_set to #c_vararg parameter
- Compiler panic: Invalid type conversion HOT 1
- On Unixoids `os.read_dir()` closes the file descriptor passed to it
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from odin.