-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
abi.cr
112 lines (99 loc) · 2.66 KB
/
abi.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# Based on https://github.com/rust-lang/rust/blob/29ac04402d53d358a1f6200bea45a301ff05b2d1/src/librustc_trans/trans/cabi.rs
abstract class LLVM::ABI
getter target_data : TargetData
getter? osx : Bool
getter? windows : Bool
def initialize(target_machine : TargetMachine)
@target_data = target_machine.data_layout
triple = target_machine.triple
@osx = !!(triple =~ /apple/)
@windows = !!(triple =~ /windows/)
end
abstract def abi_info(atys : Array(Type), rty : Type, ret_def : Bool, context : Context)
abstract def size(type : Type)
abstract def align(type : Type)
def size(type : Type, pointer_size)
case type.kind
when Type::Kind::Integer
(type.int_width + 7) // 8
when Type::Kind::Float
4
when Type::Kind::Double
8
when Type::Kind::Pointer
pointer_size
when Type::Kind::Struct
if type.packed_struct?
type.struct_element_types.reduce(0) do |memo, elem|
memo + size(elem)
end
else
size = type.struct_element_types.reduce(0) do |memo, elem|
align_offset(memo, elem) + size(elem)
end
align_offset(size, type)
end
when Type::Kind::Array
size(type.element_type) * type.array_size
else
raise "Unhandled Type::Kind in size: #{type.kind}"
end
end
def align_offset(offset, type)
align = align(type)
(offset + align - 1) // align * align
end
def align(type : Type, pointer_size)
case type.kind
when Type::Kind::Integer
(type.int_width + 7) // 8
when Type::Kind::Float
4
when Type::Kind::Double
8
when Type::Kind::Pointer
pointer_size
when Type::Kind::Struct
if type.packed_struct?
1
else
type.struct_element_types.reduce(1) do |memo, elem|
Math.max(memo, align(elem))
end
end
when Type::Kind::Array
align(type.element_type)
else
raise "Unhandled Type::Kind in align: #{type.kind}"
end
end
enum ArgKind
Direct
Indirect
Ignore
end
struct ArgType
getter kind : ArgKind
getter type : Type
getter cast : Type?
getter pad : Nil
getter attr : Attribute?
def self.direct(type, cast = nil, pad = nil, attr = nil)
new ArgKind::Direct, type, cast, pad, attr
end
def self.indirect(type, attr)
new ArgKind::Indirect, type, attr: attr
end
def self.ignore(type)
new ArgKind::Ignore, type
end
def initialize(@kind, @type, @cast = nil, @pad = nil, @attr = nil)
end
end
class FunctionType
getter arg_types : Array(ArgType)
getter return_type : ArgType
def initialize(@arg_types, @return_type)
end
end
end