/
x86.cr
75 lines (66 loc) · 2.1 KB
/
x86.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
require "../abi"
# Based on https://github.com/rust-lang/rust/blob/29ac04402d53d358a1f6200bea45a301ff05b2d1/src/librustc_trans/trans/cabi_x86.rs
class LLVM::ABI::X86 < LLVM::ABI
def abi_info(atys : Array(Type), rty : Type, ret_def : Bool, context : Context)
ret_ty = compute_return_type(rty, ret_def, context)
arg_tys = compute_arg_types(atys, context)
FunctionType.new arg_tys, ret_ty
end
def size(type : Type)
target_data.abi_size(type).to_i32
end
def align(type : Type)
target_data.abi_alignment(type).to_i32
end
private def compute_return_type(rty, ret_def, context)
if !ret_def
ArgType.direct(context.void)
elsif rty.kind == LLVM::Type::Kind::Struct
# Returning a structure. Most often, this will use
# a hidden first argument. On some platforms, though,
# small structs are returned as integers.
#
# Some links:
# http://www.angelcode.com/dev/callconv/callconv.html
# Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
if osx? || windows?
case target_data.abi_size(rty)
when 1 then ret_ty = ret_value(rty, context.int8)
when 2 then ret_ty = ret_value(rty, context.int16)
when 4 then ret_ty = ret_value(rty, context.int32)
when 8 then ret_ty = ret_value(rty, context.int64)
else ret_ty = ret_pointer(rty)
end
else
ret_pointer(rty)
end
else
non_struct(rty, context)
end
end
private def compute_arg_types(atys, context)
atys.map do |t|
case t.kind
when Type::Kind::Struct
size = target_data.abi_size(t)
if size == 0
ArgType.ignore(t)
else
ArgType.indirect(t, LLVM::Attribute::ByVal)
end
else
non_struct(t, context)
end
end
end
private def ret_value(type, cast)
ArgType.direct(type, cast)
end
private def ret_pointer(type)
ArgType.indirect(type, LLVM::Attribute::StructRet)
end
private def non_struct(type, context)
attr = type == context.int1 ? LLVM::Attribute::ZExt : nil
ArgType.direct(type, attr: attr)
end
end