@@ -135,6 +135,7 @@ def __init__(self, engine, module_name, target, embedding_map):
135
135
self .llfunction = None
136
136
self .llmap = {}
137
137
self .llobject_map = {}
138
+ self .llnowptr = None
138
139
self .phis = []
139
140
self .debug_info_emitter = DebugInfoEmitter (self .llmodule )
140
141
self .empty_metadata = self .llmodule .add_metadata ([])
@@ -146,10 +147,6 @@ def __init__(self, engine, module_name, target, embedding_map):
146
147
self .tbaa_tree ,
147
148
ll .Constant (lli64 , 1 )
148
149
])
149
- self .tbaa_now = self .llmodule .add_metadata ([
150
- ll .MetaDataString (self .llmodule , "timeline position" ),
151
- self .tbaa_tree
152
- ])
153
150
154
151
def needs_sret (self , lltyp , may_be_large = True ):
155
152
if isinstance (lltyp , ll .VoidType ):
@@ -183,14 +180,20 @@ def llty_of_type(self, typ, bare=False, for_return=False):
183
180
elif types ._is_pointer (typ ):
184
181
return llptr
185
182
elif types .is_function (typ ):
186
- sretarg = []
187
183
llretty = self .llty_of_type (typ .ret , for_return = True )
188
184
if self .needs_sret (llretty ):
189
185
sretarg = [llretty .as_pointer ()]
190
- llretty = llvoid
186
+ llretty = lli64
187
+ elif llretty != llvoid :
188
+ sretarg = []
189
+ llretty = ll .LiteralStructType ([lli64 , llretty ])
190
+ else :
191
+ sretarg = []
192
+ llretty = lli64
191
193
192
194
envarg = llptr
193
- llty = ll .FunctionType (args = sretarg + [envarg ] +
195
+ nowarg = lli64
196
+ llty = ll .FunctionType (args = sretarg + [nowarg , envarg ] +
194
197
[self .llty_of_type (typ .args [arg ])
195
198
for arg in typ .args ] +
196
199
[self .llty_of_type (ir .TOption (typ .optargs [arg ]))
@@ -354,8 +357,6 @@ def llbuiltin(self, name):
354
357
llty = ll .FunctionType (llvoid , [lli32 , llptr , llptrptr ])
355
358
elif name == "recv_rpc" :
356
359
llty = ll .FunctionType (lli32 , [llptr ])
357
- elif name == "now" :
358
- llty = lli64
359
360
elif name == "watchdog_set" :
360
361
llty = ll .FunctionType (lli32 , [lli64 ])
361
362
elif name == "watchdog_clear" :
@@ -381,9 +382,7 @@ def get_function(self, typ, name):
381
382
if llfun is None :
382
383
llfunty = self .llty_of_type (typ , bare = True )
383
384
llfun = ll .Function (self .llmodule , llfunty , name )
384
-
385
- llretty = self .llty_of_type (typ .find ().ret , for_return = True )
386
- if self .needs_sret (llretty ):
385
+ if self .has_sret (typ ):
387
386
llfun .args [0 ].add_attribute ('sret' )
388
387
return llfun
389
388
@@ -532,6 +531,10 @@ def process_function(self, func):
532
531
if func .is_cold :
533
532
self .llfunction .attributes .add ('cold' )
534
533
self .llfunction .attributes .add ('noinline' )
534
+ if 'inline' in func .flags :
535
+ self .llfunction .attributes .add ('inlinehint' )
536
+ if 'always_inline' in func .flags :
537
+ self .llfunction .attributes .add ('alwaysinline' )
535
538
536
539
self .llfunction .attributes .add ('uwtable' )
537
540
self .llfunction .attributes .personality = self .llbuiltin ("__artiq_personality" )
@@ -545,20 +548,28 @@ def process_function(self, func):
545
548
546
549
# First, map arguments.
547
550
if self .has_sret (func .type ):
548
- llactualargs = self .llfunction .args [1 :]
551
+ llactualargs = self .llfunction .args [2 :]
552
+ llnow = self .llfunction .args [1 ]
549
553
else :
550
- llactualargs = self .llfunction .args
554
+ llactualargs = self .llfunction .args [1 :]
555
+ llnow = self .llfunction .args [0 ]
551
556
552
557
for arg , llarg in zip (func .arguments , llactualargs ):
553
558
llarg .name = arg .name
554
559
self .llmap [arg ] = llarg
555
560
556
- # Second, create all basic blocks.
561
+ # Second, set up a pre-entry block.
562
+ llpreentry = self .llfunction .append_basic_block ("preentry" )
563
+ self .llbuilder .position_at_end (llpreentry )
564
+ self .llnowptr = self .llbuilder .alloca (lli64 , name = "now" )
565
+ self .llbuilder .store (llnow , self .llnowptr )
566
+
567
+ # Third, create all basic blocks.
557
568
for block in func .basic_blocks :
558
569
llblock = self .llfunction .append_basic_block (block .name )
559
570
self .llmap [block ] = llblock
560
571
561
- # Third , translate all instructions.
572
+ # Fourth , translate all instructions.
562
573
for block in func .basic_blocks :
563
574
self .llbuilder .position_at_end (self .llmap [block ])
564
575
for insn in block .instructions :
@@ -577,7 +588,11 @@ def process_function(self, func):
577
588
# using a different map (the following one).
578
589
llblock_map [block ] = self .llbuilder .basic_block
579
590
580
- # Fourth, add incoming values to phis.
591
+ # Fifth, branch from pre-entry block to the real entry block.
592
+ self .llbuilder .position_at_end (llpreentry )
593
+ self .llbuilder .branch (self .llmap [func .entry ()])
594
+
595
+ # Sixth, add incoming values to phis.
581
596
for phi , llphi in self .phis :
582
597
for value , block in phi .incoming ():
583
598
llphi .add_incoming (self .map (value ), llblock_map [block ])
@@ -1074,20 +1089,16 @@ def get_outer(llenv, env_ty):
1074
1089
# This is an identity cast at LLVM IR level.
1075
1090
return self .map (insn .operands [0 ])
1076
1091
elif insn .op == "now_mu" :
1077
- llnow = self .llbuilder .load (self .llbuiltin ("now" ), name = insn .name )
1078
- llnow .set_metadata ("tbaa" , self .tbaa_now )
1092
+ llnow = self .llbuilder .load (self .llnowptr , name = insn .name )
1079
1093
return llnow
1080
1094
elif insn .op == "at_mu" :
1081
1095
time , = insn .operands
1082
- return self .llbuilder .store (self .map (time ), self .llbuiltin ( "now" ) )
1096
+ return self .llbuilder .store (self .map (time ), self .llnowptr )
1083
1097
elif insn .op == "delay_mu" :
1084
1098
interval , = insn .operands
1085
- llnowptr = self .llbuiltin ("now" )
1086
- llnow = self .llbuilder .load (llnowptr , name = "now.old" )
1087
- llnow .set_metadata ("tbaa" , self .tbaa_now )
1099
+ llnow = self .llbuilder .load (self .llnowptr , name = "now.old" )
1088
1100
lladjusted = self .llbuilder .add (llnow , self .map (interval ), name = "now.new" )
1089
- llnowstore = self .llbuilder .store (lladjusted , llnowptr )
1090
- llnowstore .set_metadata ("tbaa" , self .tbaa_now )
1101
+ llnowstore = self .llbuilder .store (lladjusted , self .llnowptr )
1091
1102
return llnowstore
1092
1103
elif insn .op == "watchdog_set" :
1093
1104
interval , = insn .operands
@@ -1118,8 +1129,9 @@ def _prepare_closure_call(self, insn):
1118
1129
llfun = self .llbuilder .extract_value (llclosure , 1 , name = name )
1119
1130
else :
1120
1131
llfun = self .map (insn .static_target_function )
1132
+ llnow = self .llbuilder .load (self .llnowptr )
1121
1133
llenv = self .llbuilder .extract_value (llclosure , 0 , name = "env.fun" )
1122
- return llfun , [llenv ] + list (llargs )
1134
+ return llfun , [llnow , llenv ] + list (llargs )
1123
1135
1124
1136
def _prepare_ffi_call (self , insn ):
1125
1137
llargs = []
@@ -1156,6 +1168,16 @@ def _prepare_ffi_call(self, insn):
1156
1168
1157
1169
return llfun , list (llargs )
1158
1170
1171
+ def _process_closure_result (self , functionty , llresult ):
1172
+ if builtins .is_none (functionty .ret ):
1173
+ assert llresult .type == lli64
1174
+ return self .llbuilder .store (llresult , self .llnowptr )
1175
+ else :
1176
+ llnow = self .llbuilder .extract_value (llresult , 0 )
1177
+ llvalue = self .llbuilder .extract_value (llresult , 1 )
1178
+ self .llbuilder .store (llnow , self .llnowptr )
1179
+ return llvalue
1180
+
1159
1181
# See session.c:{send,receive}_rpc_value and comm_generic.py:_{send,receive}_rpc_value.
1160
1182
def _rpc_tag (self , typ , error_handler ):
1161
1183
typ = typ .find ()
@@ -1340,11 +1362,14 @@ def process_Call(self, insn):
1340
1362
if types .is_c_function (functiontyp ) and 'nowrite' in functiontyp .flags :
1341
1363
llcall .set_metadata ('tbaa' , self .tbaa_nowrite_call )
1342
1364
1365
+ if types .is_python_function (functiontyp ):
1366
+ llresult = self ._process_closure_result (functiontyp , llresult )
1367
+
1343
1368
return llresult
1344
1369
1345
1370
def process_Invoke (self , insn ):
1346
1371
functiontyp = insn .target_function ().type
1347
- llnormalblock = self .map ( insn . normal_target () )
1372
+ llnormalblock = self .llfunction . append_basic_block ( "invoke.post" )
1348
1373
llunwindblock = self .map (insn .exception_target ())
1349
1374
if types .is_rpc (functiontyp ):
1350
1375
return self ._build_rpc (insn .target_function ().loc ,
@@ -1366,14 +1391,19 @@ def process_Invoke(self, insn):
1366
1391
1367
1392
self .llbuilder .call (self .llbuiltin ("llvm.stackrestore" ), [llstackptr ])
1368
1393
else :
1369
- llcall = self .llbuilder .invoke (llfun , llargs , llnormalblock , llunwindblock ,
1370
- name = insn .name )
1394
+ llcall = llresult = self .llbuilder .invoke (llfun , llargs , llnormalblock , llunwindblock ,
1395
+ name = insn .name )
1371
1396
1372
1397
# See the comment in process_Call.
1373
1398
if types .is_c_function (functiontyp ) and 'nowrite' in functiontyp .flags :
1374
1399
llcall .set_metadata ('tbaa' , self .tbaa_nowrite_call )
1375
1400
1376
- return llcall
1401
+ self .llbuilder .position_at_end (llnormalblock )
1402
+ if types .is_python_function (functiontyp ):
1403
+ llresult = self ._process_closure_result (functiontyp , llresult )
1404
+ self .llbuilder .branch (self .map (insn .normal_target ()))
1405
+
1406
+ return llresult
1377
1407
1378
1408
def _quote (self , value , typ , path ):
1379
1409
value_id = id (value )
@@ -1497,15 +1527,19 @@ def process_IndirectBranch(self, insn):
1497
1527
return llinsn
1498
1528
1499
1529
def process_Return (self , insn ):
1530
+ llnow = self .llbuilder .load (self .llnowptr )
1500
1531
if builtins .is_none (insn .value ().type ):
1501
- return self .llbuilder .ret_void ( )
1532
+ return self .llbuilder .ret ( llnow )
1502
1533
else :
1503
1534
llvalue = self .map (insn .value ())
1504
1535
if self .needs_sret (llvalue .type ):
1505
1536
self .llbuilder .store (llvalue , self .llfunction .args [0 ])
1506
- return self .llbuilder .ret_void ( )
1537
+ return self .llbuilder .ret ( llnow )
1507
1538
else :
1508
- return self .llbuilder .ret (llvalue )
1539
+ llret = ll .Constant (self .llfunction .ftype .return_type , ll .Undefined )
1540
+ llret = self .llbuilder .insert_value (llret , llnow , 0 )
1541
+ llret = self .llbuilder .insert_value (llret , llvalue , 1 )
1542
+ return self .llbuilder .ret (llret )
1509
1543
1510
1544
def process_Unreachable (self , insn ):
1511
1545
return self .llbuilder .unreachable ()
0 commit comments