/
arm.cr
65 lines (58 loc) · 1.62 KB
/
arm.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
require "../abi"
# Based on https://github.com/rust-lang/rust/blob/dfe8bd10fe6763e0a1d5d55fa2574ecba27d3e2e/src/librustc_trans/cabi_arm.rs
class LLVM::ABI::ARM < 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 align(type : Type)
align(type, 4)
end
def size(type : Type)
size(type, 4)
end
def register?(type)
case type.kind
when Type::Kind::Integer, Type::Kind::Float, Type::Kind::Double, Type::Kind::Pointer
true
else
false
end
end
private def compute_return_type(rty, ret_def, context)
if !ret_def
ArgType.direct(context.void)
elsif register?(rty)
non_struct(rty, context)
else
case size(rty)
when 1
ArgType.direct(rty, context.int8)
when 2
ArgType.direct(rty, context.int16)
when 3, 4
ArgType.direct(rty, context.int32)
else
ArgType.indirect(rty, LLVM::Attribute::StructRet)
end
end
end
private def compute_arg_types(atys, context)
atys.map do |aty|
if register?(aty)
non_struct(aty, context)
else
if align(aty) <= 4
ArgType.direct(aty, context.int32.array(((size(aty) + 3) / 4).to_u64))
else
ArgType.direct(aty, context.int64.array(((size(aty) + 7) / 8).to_u64))
end
end
end
end
private def non_struct(type, context)
attr = type == context.int1 ? LLVM::Attribute::ZExt : nil
ArgType.direct(type, attr: attr)
end
end