3
3
import llvmlite .ir as ll
4
4
import llvmlite .binding as llvm
5
5
6
- from artiq .py2llvm import base_types
6
+ from artiq .py2llvm import base_types , fractions , lists
7
7
from artiq .language import units
8
8
9
9
12
12
llvm .initialize_all_asmprinters ()
13
13
14
14
_syscalls = {
15
- "rpc" : "i+:i" ,
16
15
"gpio_set" : "ib:n" ,
17
16
"rtio_oe" : "ib:n" ,
18
17
"rtio_set" : "Iii:n" ,
23
22
"dds_program" : "Iiiiibb:n" ,
24
23
}
25
24
26
- _chr_to_type = {
27
- "n" : lambda : ll .VoidType (),
28
- "b" : lambda : ll .IntType (1 ),
29
- "i" : lambda : ll .IntType (32 ),
30
- "I" : lambda : ll .IntType (64 )
31
- }
32
25
33
- _chr_to_value = {
34
- "n" : lambda : base_types .VNone (),
35
- "b" : lambda : base_types .VBool (),
36
- "i" : lambda : base_types .VInt (),
37
- "I" : lambda : base_types .VInt (64 )
38
- }
26
+ def _chr_to_type (c ):
27
+ if c == "n" :
28
+ return ll .VoidType ()
29
+ if c == "b" :
30
+ return ll .IntType (1 )
31
+ if c == "i" :
32
+ return ll .IntType (32 )
33
+ if c == "I" :
34
+ return ll .IntType (64 )
35
+ raise ValueError
39
36
40
37
41
38
def _str_to_functype (s ):
42
39
assert (s [- 2 ] == ":" )
43
- type_ret = _chr_to_type [s [- 1 ]]()
44
-
45
- var_arg_fixcount = None
46
- type_args = []
47
- for n , c in enumerate (s [:- 2 ]):
48
- if c == "+" :
49
- type_args .append (ll .IntType (32 ))
50
- var_arg_fixcount = n
51
- elif c != "n" :
52
- type_args .append (_chr_to_type [c ]())
53
- return (var_arg_fixcount ,
54
- ll .FunctionType (type_ret , type_args ,
55
- var_arg = var_arg_fixcount is not None ))
40
+ type_ret = _chr_to_type (s [- 1 ])
41
+ type_args = [_chr_to_type (c ) for c in s [:- 2 ] if c != "n" ]
42
+ return ll .FunctionType (type_ret , type_args )
43
+
44
+
45
+ def _chr_to_value (c ):
46
+ if c == "n" :
47
+ return base_types .VNone ()
48
+ if c == "b" :
49
+ return base_types .VBool ()
50
+ if c == "i" :
51
+ return base_types .VInt ()
52
+ if c == "I" :
53
+ return base_types .VInt (64 )
54
+ raise ValueError
55
+
56
+
57
+ def _value_to_str (v ):
58
+ if isinstance (v , base_types .VNone ):
59
+ return "n"
60
+ if isinstance (v , base_types .VBool ):
61
+ return "b"
62
+ if isinstance (v , base_types .VInt ):
63
+ if v .nbits == 32 :
64
+ return "i"
65
+ if v .nbits == 64 :
66
+ return "I"
67
+ raise ValueError
68
+ if isinstance (v , base_types .VFloat ):
69
+ return "f"
70
+ if isinstance (v , fractions .VFraction ):
71
+ return "F"
72
+ if isinstance (v , lists .VList ):
73
+ return "l" + _value_to_str (v .el_type )
74
+ raise ValueError
56
75
57
76
58
77
class LinkInterface :
59
78
def init_module (self , module ):
60
79
self .module = module
61
80
llvm_module = self .module .llvm_module
62
81
82
+ # RPC
83
+ func_type = ll .FunctionType (ll .IntType (32 ), [ll .IntType (32 )],
84
+ var_arg = 1 )
85
+ self .rpc = ll .Function (llvm_module , func_type , "__syscall_rpc" )
86
+
63
87
# syscalls
64
88
self .syscalls = dict ()
65
- self .var_arg_fixcount = dict ()
66
89
for func_name , func_type_str in _syscalls .items ():
67
- var_arg_fixcount , func_type = _str_to_functype (func_type_str )
68
- if var_arg_fixcount is not None :
69
- self .var_arg_fixcount [func_name ] = var_arg_fixcount
90
+ func_type = _str_to_functype (func_type_str )
70
91
self .syscalls [func_name ] = ll .Function (
71
92
llvm_module , func_type , "__syscall_" + func_name )
72
93
@@ -91,19 +112,48 @@ def init_module(self, module):
91
112
self .eh_raise = ll .Function (llvm_module , func_type , "__eh_raise" )
92
113
self .eh_raise .attributes .add ("noreturn" )
93
114
94
- def build_syscall (self , syscall_name , args , builder ):
95
- r = _chr_to_value [_syscalls [syscall_name ][- 1 ]]()
115
+ def _build_rpc (self , args , builder ):
116
+ r = base_types .VInt ()
117
+ if builder is not None :
118
+ new_args = []
119
+ new_args .append (args [0 ].auto_load (builder )) # RPC number
120
+ for arg in args [1 :]:
121
+ # type tag
122
+ arg_type_str = _value_to_str (arg )
123
+ arg_type_int = 0
124
+ for c in reversed (arg_type_str ):
125
+ arg_type_int <<= 8
126
+ arg_type_int |= ord (c )
127
+ new_args .append (ll .Constant (ll .IntType (32 ), arg_type_int ))
128
+
129
+ # pointer to value
130
+ if not isinstance (arg , base_types .VNone ):
131
+ if isinstance (arg .llvm_value .type , ll .PointerType ):
132
+ new_args .append (arg .llvm_value )
133
+ else :
134
+ arg_ptr = arg .new ()
135
+ arg_ptr .alloca (builder )
136
+ arg_ptr .auto_store (builder , arg .llvm_value )
137
+ new_args .append (arg_ptr .llvm_value )
138
+ # end marker
139
+ new_args .append (ll .Constant (ll .IntType (32 ), 0 ))
140
+ r .auto_store (builder , builder .call (self .rpc , new_args ))
141
+ return r
142
+
143
+ def _build_regular_syscall (self , syscall_name , args , builder ):
144
+ r = _chr_to_value (_syscalls [syscall_name ][- 1 ])
96
145
if builder is not None :
97
146
args = [arg .auto_load (builder ) for arg in args ]
98
- if syscall_name in self .var_arg_fixcount :
99
- fixcount = self .var_arg_fixcount [syscall_name ]
100
- args = args [:fixcount ] \
101
- + [ll .Constant (ll .IntType (32 ), len (args ) - fixcount )] \
102
- + args [fixcount :]
103
147
r .auto_store (builder , builder .call (self .syscalls [syscall_name ],
104
148
args ))
105
149
return r
106
150
151
+ def build_syscall (self , syscall_name , args , builder ):
152
+ if syscall_name == "rpc" :
153
+ return self ._build_rpc (args , builder )
154
+ else :
155
+ return self ._build_regular_syscall (syscall_name , args , builder )
156
+
107
157
def build_catch (self , builder ):
108
158
jmpbuf = builder .call (self .eh_push , [])
109
159
exception_occured = builder .call (self .eh_setjmp , [jmpbuf ])
0 commit comments