C ABI and compiler rt improvements for ARM
* add __multi3 compiler rt function. See #1290 * compiler rt includes ARM functions for thumb and aarch64 and other sub-arches left out. See #1526 * support C ABI for returning structs on ARM. see #1481master
parent
67fb4d1359
commit
3e72411db0
|
@ -625,6 +625,7 @@ set(ZIG_STD_FILES
|
|||
"special/compiler_rt/floatuntitf.zig"
|
||||
"special/compiler_rt/index.zig"
|
||||
"special/compiler_rt/muloti4.zig"
|
||||
"special/compiler_rt/multi3.zig"
|
||||
"special/compiler_rt/truncXfYf2.zig"
|
||||
"special/compiler_rt/udivmod.zig"
|
||||
"special/compiler_rt/udivmoddi4.zig"
|
||||
|
|
|
@ -1084,6 +1084,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
|
|||
}
|
||||
zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
|
||||
buf_ptr(&fn_type_id->return_type->name));
|
||||
} else if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb) {
|
||||
return type_size(g, fn_type_id->return_type) > 16;
|
||||
}
|
||||
zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ comptime {
|
|||
@export("___chkstk_ms", ___chkstk_ms, linkage);
|
||||
}
|
||||
@export("__divti3", @import("divti3.zig").__divti3_windows_x86_64, linkage);
|
||||
@export("__multi3", @import("multi3.zig").__multi3_windows_x86_64, linkage);
|
||||
@export("__muloti4", @import("muloti4.zig").__muloti4_windows_x86_64, linkage);
|
||||
@export("__udivti3", @import("udivti3.zig").__udivti3_windows_x86_64, linkage);
|
||||
@export("__udivmodti4", @import("udivmodti4.zig").__udivmodti4_windows_x86_64, linkage);
|
||||
|
@ -89,6 +90,7 @@ comptime {
|
|||
}
|
||||
} else {
|
||||
@export("__divti3", @import("divti3.zig").__divti3, linkage);
|
||||
@export("__multi3", @import("multi3.zig").__multi3, linkage);
|
||||
@export("__muloti4", @import("muloti4.zig").__muloti4, linkage);
|
||||
@export("__udivti3", @import("udivti3.zig").__udivti3, linkage);
|
||||
@export("__udivmodti4", @import("udivmodti4.zig").__udivmodti4, linkage);
|
||||
|
@ -149,6 +151,7 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult
|
|||
|
||||
fn isArmArch() bool {
|
||||
return switch (builtin.arch) {
|
||||
builtin.Arch.armv8_3a,
|
||||
builtin.Arch.armv8_2a,
|
||||
builtin.Arch.armv8_1a,
|
||||
builtin.Arch.armv8,
|
||||
|
@ -160,6 +163,7 @@ fn isArmArch() bool {
|
|||
builtin.Arch.armv7m,
|
||||
builtin.Arch.armv7s,
|
||||
builtin.Arch.armv7k,
|
||||
builtin.Arch.armv7ve,
|
||||
builtin.Arch.armv6,
|
||||
builtin.Arch.armv6m,
|
||||
builtin.Arch.armv6k,
|
||||
|
@ -167,6 +171,7 @@ fn isArmArch() bool {
|
|||
builtin.Arch.armv5,
|
||||
builtin.Arch.armv5te,
|
||||
builtin.Arch.armv4t,
|
||||
builtin.Arch.armebv8_3a,
|
||||
builtin.Arch.armebv8_2a,
|
||||
builtin.Arch.armebv8_1a,
|
||||
builtin.Arch.armebv8,
|
||||
|
@ -178,6 +183,7 @@ fn isArmArch() bool {
|
|||
builtin.Arch.armebv7m,
|
||||
builtin.Arch.armebv7s,
|
||||
builtin.Arch.armebv7k,
|
||||
builtin.Arch.armebv7ve,
|
||||
builtin.Arch.armebv6,
|
||||
builtin.Arch.armebv6m,
|
||||
builtin.Arch.armebv6k,
|
||||
|
@ -185,6 +191,22 @@ fn isArmArch() bool {
|
|||
builtin.Arch.armebv5,
|
||||
builtin.Arch.armebv5te,
|
||||
builtin.Arch.armebv4t,
|
||||
builtin.Arch.aarch64v8_3a,
|
||||
builtin.Arch.aarch64v8_2a,
|
||||
builtin.Arch.aarch64v8_1a,
|
||||
builtin.Arch.aarch64v8,
|
||||
builtin.Arch.aarch64v8r,
|
||||
builtin.Arch.aarch64v8m_baseline,
|
||||
builtin.Arch.aarch64v8m_mainline,
|
||||
builtin.Arch.aarch64_bev8_3a,
|
||||
builtin.Arch.aarch64_bev8_2a,
|
||||
builtin.Arch.aarch64_bev8_1a,
|
||||
builtin.Arch.aarch64_bev8,
|
||||
builtin.Arch.aarch64_bev8r,
|
||||
builtin.Arch.aarch64_bev8m_baseline,
|
||||
builtin.Arch.aarch64_bev8m_mainline,
|
||||
builtin.Arch.thumb,
|
||||
builtin.Arch.thumbeb,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
const builtin = @import("builtin");
|
||||
const compiler_rt = @import("index.zig");
|
||||
|
||||
// Ported from git@github.com:llvm-project/llvm-project-20170507.git
|
||||
// ae684fad6d34858c014c94da69c15e7774a633c3
|
||||
// 2018-08-13
|
||||
|
||||
pub extern fn __multi3(a: i128, b: i128) i128 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
const x = twords{.all = a};
|
||||
const y = twords{.all = b};
|
||||
var r = twords{.all = __mulddi3(x.s.low, y.s.low)};
|
||||
r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high;
|
||||
return r.all;
|
||||
}
|
||||
|
||||
pub extern fn __multi3_windows_x86_64(a: *const i128, b: *const i128) void {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
compiler_rt.setXmm0(i128, __multi3(a.*, b.*));
|
||||
}
|
||||
|
||||
fn __mulddi3(a: u64, b: u64) i128 {
|
||||
const bits_in_dword_2 = (@sizeOf(i64) * 8) / 2;
|
||||
const lower_mask = ~u64(0) >> bits_in_dword_2;
|
||||
var r: twords = undefined;
|
||||
r.s.low = (a & lower_mask) *% (b & lower_mask);
|
||||
var t: u64 = r.s.low >> bits_in_dword_2;
|
||||
r.s.low &= lower_mask;
|
||||
t +%= (a >> bits_in_dword_2) *% (b & lower_mask);
|
||||
r.s.low +%= (t & lower_mask) << bits_in_dword_2;
|
||||
r.s.high = t >> bits_in_dword_2;
|
||||
t = r.s.low >> bits_in_dword_2;
|
||||
r.s.low &= lower_mask;
|
||||
t +%= (b >> bits_in_dword_2) *% (a & lower_mask);
|
||||
r.s.low +%= (t & lower_mask) << bits_in_dword_2;
|
||||
r.s.high +%= t >> bits_in_dword_2;
|
||||
r.s.high +%= (a >> bits_in_dword_2) *% (b >> bits_in_dword_2);
|
||||
return r.all;
|
||||
}
|
||||
|
||||
const twords = extern union {
|
||||
all: i128,
|
||||
s: S,
|
||||
|
||||
const S = if (builtin.endian == builtin.Endian.Little) struct {
|
||||
low: u64,
|
||||
high: u64,
|
||||
} else struct {
|
||||
high: u64,
|
||||
low: u64,
|
||||
};
|
||||
};
|
||||
|
||||
test "import multi3" {
|
||||
_ = @import("multi3_test.zig");
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
const __multi3 = @import("multi3.zig").__multi3;
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
fn test__multi3(a: i128, b: i128, expected: i128) void {
|
||||
const x = __multi3(a, b);
|
||||
assert(x == expected);
|
||||
}
|
||||
|
||||
test "multi3" {
|
||||
test__multi3(0, 0, 0);
|
||||
test__multi3(0, 1, 0);
|
||||
test__multi3(1, 0, 0);
|
||||
test__multi3(0, 10, 0);
|
||||
test__multi3(10, 0, 0);
|
||||
test__multi3(0, 81985529216486895, 0);
|
||||
test__multi3(81985529216486895, 0, 0);
|
||||
|
||||
test__multi3(0, -1, 0);
|
||||
test__multi3(-1, 0, 0);
|
||||
test__multi3(0, -10, 0);
|
||||
test__multi3(-10, 0, 0);
|
||||
test__multi3(0, -81985529216486895, 0);
|
||||
test__multi3(-81985529216486895, 0, 0);
|
||||
|
||||
test__multi3(1, 1, 1);
|
||||
test__multi3(1, 10, 10);
|
||||
test__multi3(10, 1, 10);
|
||||
test__multi3(1, 81985529216486895, 81985529216486895);
|
||||
test__multi3(81985529216486895, 1, 81985529216486895);
|
||||
|
||||
test__multi3(1, -1, -1);
|
||||
test__multi3(1, -10, -10);
|
||||
test__multi3(-10, 1, -10);
|
||||
test__multi3(1, -81985529216486895, -81985529216486895);
|
||||
test__multi3(-81985529216486895, 1, -81985529216486895);
|
||||
|
||||
test__multi3(3037000499, 3037000499, 9223372030926249001);
|
||||
test__multi3(-3037000499, 3037000499, -9223372030926249001);
|
||||
test__multi3(3037000499, -3037000499, -9223372030926249001);
|
||||
test__multi3(-3037000499, -3037000499, 9223372030926249001);
|
||||
|
||||
test__multi3(4398046511103, 2097152, 9223372036852678656);
|
||||
test__multi3(-4398046511103, 2097152, -9223372036852678656);
|
||||
test__multi3(4398046511103, -2097152, -9223372036852678656);
|
||||
test__multi3(-4398046511103, -2097152, 9223372036852678656);
|
||||
|
||||
test__multi3(2097152, 4398046511103, 9223372036852678656);
|
||||
test__multi3(-2097152, 4398046511103, -9223372036852678656);
|
||||
test__multi3(2097152, -4398046511103, -9223372036852678656);
|
||||
test__multi3(-2097152, -4398046511103, 9223372036852678656);
|
||||
|
||||
test__multi3(0x00000000000000B504F333F9DE5BE000, 0x000000000000000000B504F333F9DE5B,
|
||||
0x7FFFFFFFFFFFF328DF915DA296E8A000);
|
||||
}
|
Loading…
Reference in New Issue