Skip to content

Instantly share code, notes, and snippets.

@klutzy
Last active August 29, 2015 13:56
Show Gist options
  • Save klutzy/9250639 to your computer and use it in GitHub Desktop.
Save klutzy/9250639 to your computer and use it in GitHub Desktop.
rust struct abi
#include <stdio.h>
struct Coord {
short x;
short y;
};
void __stdcall std_func(int a, struct Coord coord, int b) {
printf("[std_func] a: %d / coord.x: %d / coord.y: %d / b: %d\n", a, coord.x, coord.y, b);
}
void c_func(int a, struct Coord coord, int b) {
printf("[c_func] a: %d / coord.x: %d / coord.y: %d / b: %d\n", a, coord.x, coord.y, b);
}
struct Coord {
short x;
short y;
};
void __stdcall std_func(int a, struct Coord coord, int b);
void c_func(int a, struct Coord coord, int b);
int main() {
struct Coord coord = { 0x20, 0x30 };
std_func(0x10, coord, 0x40);
c_func(0x10, coord, 0x40);
}
; ModuleID = 'hand.c'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"
target triple = "i686-pc-win32"
%struct.Coord = type { i16, i16 }
@main.coord = private unnamed_addr constant %struct.Coord { i16 32, i16 48 }
define i32 @main() nounwind {
%coord = alloca %struct.Coord
%__arg = alloca i32
%__arg1 = alloca %struct.Coord
%__arg2 = alloca i32
%__arg3 = alloca i32
%__arg4 = alloca %struct.Coord
%__arg5 = alloca i32
%v0 = getelementptr inbounds %struct.Coord* %coord, i32 0, i32 0
store i16 32, i16* %v0
%v1 = getelementptr inbounds %struct.Coord* %coord, i32 0, i32 1
store i16 48, i16* %v1
%v2 = load %struct.Coord* %coord
store i32 16, i32* %__arg
%v3 = load i32* %__arg
store %struct.Coord %v2, %struct.Coord* %__arg1
%v4 = load %struct.Coord* %__arg1
store i32 64, i32* %__arg2
%v5 = load i32* %__arg2
call x86_stdcallcc void @std_func(i32 %v3, %struct.Coord* byval align 4 %__arg1, i32 %v5)
store i32 16, i32* %__arg3
%v7 = load i32* %__arg3
%v6 = load %struct.Coord* %coord
store %struct.Coord %v6, %struct.Coord* %__arg4
%v8 = load %struct.Coord* %__arg4
store i32 64, i32* %__arg5
%v9 = load i32* %__arg5
call void @c_func(i32 %v7, %struct.Coord* byval %__arg4, i32 %v9)
ret i32 0
}
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
declare x86_stdcallcc void @std_func(i32, %struct.Coord* byval align 4, i32)
declare void @c_func(i32, %struct.Coord* byval align 4, i32)
all: c.dll rs.exe cl.exe hand.exe
c.dll: c.c
gcc -shared -o $@ $<
rs.exe: rs.rs
rustc --opt-level=0 -Z no-opt -L . $< -o rs.ll --emit ir
rustc --opt-level=0 -Z no-opt -L . $< -o rs.s --emit asm
rustc --opt-level=0 -Z no-opt -L . $< -o $@ -C save-temps
cl.exe: cl.c
clang -opt=level=0 -o cl.ll $< -emit-llvm -S
llc -O0 -filetype=asm -o cl.s cl.ll
gcc -o $@ cl.s -L. -lc
hand.exe: hand.ll
llc -O0 -filetype=asm -o hand.s $<
gcc -o $@ hand.s -L. -lc
.PHONY: ta
ta: all
@echo "clang:" && ./cl
@echo "rust:" && ./rs
@echo "hand:" && ./hand
.PHONY: clean
clean:
rm *.dll *.exe *.s *.o
struct Coord {
x: i16,
y: i16,
}
#[link(name = "c")]
extern "stdcall" {
fn std_func(a: i32, coord: Coord, b: i32);
}
extern {
fn c_func(a: i32, coord: Coord, b: i32);
}
fn main() {
let coord = Coord {
x: 0x20,
y: 0x30,
};
unsafe {
std_func(0x10, coord, 0x40);
c_func(0x10, coord, 0x40);
}
}
@klutzy
Copy link
Author

klutzy commented Feb 28, 2014

$ make ta
clang:
[std_func] a: 16 / coord.x: 32 / coord.y: 48 / b: 64
[c_func]   a: 16 / coord.x: 32 / coord.y: 48 / b: 64
rust:
[std_func] a: 16 / coord.x: 32 / coord.y: 0 / b: 48
[c_func]   a: 16 / coord.x: 16 / coord.y: 0 / b: 0
hand:
[std_func] a: 16 / coord.x: 32 / coord.y: 48 / b: 64
[c_func]   a: 16 / coord.x: 32 / coord.y: 48 / b: 64
  • clang: declare x86_stdcallcc void @std_func(i32, %struct.Coord* byval align 4, i32)
  • rust: declare x86_stdcallcc void @std_func(i32, %struct.Coord, i32) unnamed_addr
  • * byval is needed to conform to win32 abi

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