1
- use std:: borrow:: Cow ;
1
+ use std:: borrow:: { Borrow , Cow } ;
2
2
use std:: ops:: Deref ;
3
3
use std:: { iter, ptr} ;
4
4
@@ -31,27 +31,135 @@ use tracing::{debug, instrument};
31
31
use crate :: abi:: FnAbiLlvmExt ;
32
32
use crate :: attributes;
33
33
use crate :: common:: Funclet ;
34
- use crate :: context:: CodegenCx ;
34
+ use crate :: context:: { CodegenCx , SimpleCx } ;
35
35
use crate :: llvm:: { self , AtomicOrdering , AtomicRmwBinOp , BasicBlock , False , True } ;
36
36
use crate :: type_:: Type ;
37
37
use crate :: type_of:: LayoutLlvmExt ;
38
38
use crate :: value:: Value ;
39
39
40
- // All Builders must have an llfn associated with them
41
40
#[ must_use]
42
- pub ( crate ) struct Builder < ' a , ' ll , ' tcx > {
41
+ pub ( crate ) struct GenericBuilder < ' a , ' ll , CX : Borrow < SimpleCx < ' ll > > > {
43
42
pub llbuilder : & ' ll mut llvm:: Builder < ' ll > ,
44
- pub cx : & ' a CodegenCx < ' ll , ' tcx > ,
43
+ pub cx : & ' a CX ,
45
44
}
46
45
47
- impl Drop for Builder < ' _ , ' _ , ' _ > {
46
+ pub ( crate ) type SBuilder < ' a , ' ll > = GenericBuilder < ' a , ' ll , SimpleCx < ' ll > > ;
47
+ pub ( crate ) type Builder < ' a , ' ll , ' tcx > = GenericBuilder < ' a , ' ll , CodegenCx < ' ll , ' tcx > > ;
48
+
49
+ impl < ' a , ' ll , CX : Borrow < SimpleCx < ' ll > > > Drop for GenericBuilder < ' a , ' ll , CX > {
48
50
fn drop ( & mut self ) {
49
51
unsafe {
50
52
llvm:: LLVMDisposeBuilder ( & mut * ( self . llbuilder as * mut _ ) ) ;
51
53
}
52
54
}
53
55
}
54
56
57
+ impl < ' a , ' ll > SBuilder < ' a , ' ll > {
58
+ fn call (
59
+ & mut self ,
60
+ llty : & ' ll Type ,
61
+ llfn : & ' ll Value ,
62
+ args : & [ & ' ll Value ] ,
63
+ funclet : Option < & Funclet < ' ll > > ,
64
+ ) -> & ' ll Value {
65
+ debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
66
+
67
+ let args = self . check_call ( "call" , llty, llfn, args) ;
68
+ let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
69
+ let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
70
+ if let Some ( funclet_bundle) = funclet_bundle {
71
+ bundles. push ( funclet_bundle) ;
72
+ }
73
+
74
+ let call = unsafe {
75
+ llvm:: LLVMBuildCallWithOperandBundles (
76
+ self . llbuilder ,
77
+ llty,
78
+ llfn,
79
+ args. as_ptr ( ) as * const & llvm:: Value ,
80
+ args. len ( ) as c_uint ,
81
+ bundles. as_ptr ( ) ,
82
+ bundles. len ( ) as c_uint ,
83
+ c"" . as_ptr ( ) ,
84
+ )
85
+ } ;
86
+ call
87
+ }
88
+
89
+ fn with_scx ( scx : & ' a SimpleCx < ' ll > ) -> Self {
90
+ // Create a fresh builder from the simple context.
91
+ let llbuilder = unsafe { llvm:: LLVMCreateBuilderInContext ( scx. llcx ) } ;
92
+ SBuilder { llbuilder, cx : scx }
93
+ }
94
+ }
95
+ impl < ' a , ' ll , CX : Borrow < SimpleCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
96
+ pub ( crate ) fn bitcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
97
+ unsafe { llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, UNNAMED ) }
98
+ }
99
+
100
+ fn ret_void ( & mut self ) {
101
+ unsafe {
102
+ llvm:: LLVMBuildRetVoid ( self . llbuilder ) ;
103
+ }
104
+ }
105
+
106
+ fn ret ( & mut self , v : & ' ll Value ) {
107
+ unsafe {
108
+ llvm:: LLVMBuildRet ( self . llbuilder , v) ;
109
+ }
110
+ }
111
+ }
112
+ impl < ' a , ' ll > SBuilder < ' a , ' ll > {
113
+ fn build ( cx : & ' a SimpleCx < ' ll > , llbb : & ' ll BasicBlock ) -> SBuilder < ' a , ' ll > {
114
+ let bx = SBuilder :: with_scx ( cx) ;
115
+ unsafe {
116
+ llvm:: LLVMPositionBuilderAtEnd ( bx. llbuilder , llbb) ;
117
+ }
118
+ bx
119
+ }
120
+
121
+ fn check_call < ' b > (
122
+ & mut self ,
123
+ typ : & str ,
124
+ fn_ty : & ' ll Type ,
125
+ llfn : & ' ll Value ,
126
+ args : & ' b [ & ' ll Value ] ,
127
+ ) -> Cow < ' b , [ & ' ll Value ] > {
128
+ assert ! (
129
+ self . cx. type_kind( fn_ty) == TypeKind :: Function ,
130
+ "builder::{typ} not passed a function, but {fn_ty:?}"
131
+ ) ;
132
+
133
+ let param_tys = self . cx . func_params_types ( fn_ty) ;
134
+
135
+ let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
136
+ . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
137
+
138
+ if all_args_match {
139
+ return Cow :: Borrowed ( args) ;
140
+ }
141
+
142
+ let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
143
+ . enumerate ( )
144
+ . map ( |( i, ( expected_ty, & actual_val) ) | {
145
+ let actual_ty = self . cx . val_ty ( actual_val) ;
146
+ if expected_ty != actual_ty {
147
+ debug ! (
148
+ "type mismatch in function call of {:?}. \
149
+ Expected {:?} for param {}, got {:?}; injecting bitcast",
150
+ llfn, expected_ty, i, actual_ty
151
+ ) ;
152
+ self . bitcast ( actual_val, expected_ty)
153
+ } else {
154
+ actual_val
155
+ }
156
+ } )
157
+ . collect ( ) ;
158
+
159
+ Cow :: Owned ( casted_args)
160
+ }
161
+ }
162
+
55
163
/// Empty string, to be used where LLVM expects an instruction name, indicating
56
164
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
57
165
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
@@ -1222,6 +1330,14 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
1222
1330
}
1223
1331
1224
1332
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1333
+ fn build ( cx : & ' a CodegenCx < ' ll , ' tcx > , llbb : & ' ll BasicBlock ) -> Builder < ' a , ' ll , ' tcx > {
1334
+ let bx = Builder :: with_cx ( cx) ;
1335
+ unsafe {
1336
+ llvm:: LLVMPositionBuilderAtEnd ( bx. llbuilder , llbb) ;
1337
+ }
1338
+ bx
1339
+ }
1340
+
1225
1341
fn with_cx ( cx : & ' a CodegenCx < ' ll , ' tcx > ) -> Self {
1226
1342
// Create a fresh builder from the crate context.
1227
1343
let llbuilder = unsafe { llvm:: LLVMCreateBuilderInContext ( cx. llcx ) } ;
@@ -1231,13 +1347,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1231
1347
pub ( crate ) fn llfn ( & self ) -> & ' ll Value {
1232
1348
unsafe { llvm:: LLVMGetBasicBlockParent ( self . llbb ( ) ) }
1233
1349
}
1350
+ }
1234
1351
1352
+ impl < ' a , ' ll , CX : Borrow < SimpleCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
1235
1353
fn position_at_start ( & mut self , llbb : & ' ll BasicBlock ) {
1236
1354
unsafe {
1237
1355
llvm:: LLVMRustPositionBuilderAtStart ( self . llbuilder , llbb) ;
1238
1356
}
1239
1357
}
1240
-
1358
+ }
1359
+ impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1241
1360
fn align_metadata ( & mut self , load : & ' ll Value , align : Align ) {
1242
1361
unsafe {
1243
1362
let md = [ llvm:: LLVMValueAsMetadata ( self . cx . const_u64 ( align. bytes ( ) ) ) ] ;
@@ -1259,7 +1378,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1259
1378
self . set_metadata ( inst, llvm:: MD_unpredictable , md) ;
1260
1379
}
1261
1380
}
1262
-
1381
+ }
1382
+ impl < ' a , ' ll , CX : Borrow < SimpleCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
1263
1383
pub ( crate ) fn minnum ( & mut self , lhs : & ' ll Value , rhs : & ' ll Value ) -> & ' ll Value {
1264
1384
unsafe { llvm:: LLVMRustBuildMinNum ( self . llbuilder , lhs, rhs) }
1265
1385
}
@@ -1360,7 +1480,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1360
1480
let ret = unsafe { llvm:: LLVMBuildCatchRet ( self . llbuilder , funclet. cleanuppad ( ) , unwind) } ;
1361
1481
ret. expect ( "LLVM does not have support for catchret" )
1362
1482
}
1483
+ }
1363
1484
1485
+ impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1364
1486
fn check_call < ' b > (
1365
1487
& mut self ,
1366
1488
typ : & str ,
@@ -1401,11 +1523,13 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1401
1523
1402
1524
Cow :: Owned ( casted_args)
1403
1525
}
1404
-
1526
+ }
1527
+ impl < ' a , ' ll , CX : Borrow < SimpleCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
1405
1528
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
1406
1529
unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
1407
1530
}
1408
-
1531
+ }
1532
+ impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1409
1533
pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
1410
1534
let ( ty, f) = self . cx . get_intrinsic ( intrinsic) ;
1411
1535
self . call ( ty, None , None , f, args, None , None )
@@ -1423,7 +1547,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1423
1547
1424
1548
self . call_intrinsic ( intrinsic, & [ self . cx . const_u64 ( size) , ptr] ) ;
1425
1549
}
1426
-
1550
+ }
1551
+ impl < ' a , ' ll , CX : Borrow < SimpleCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
1427
1552
pub ( crate ) fn phi (
1428
1553
& mut self ,
1429
1554
ty : & ' ll Type ,
@@ -1443,7 +1568,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1443
1568
llvm:: LLVMAddIncoming ( phi, & val, & bb, 1 as c_uint ) ;
1444
1569
}
1445
1570
}
1446
-
1571
+ }
1572
+ impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1447
1573
fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
1448
1574
let src_ty = self . cx . val_ty ( val) ;
1449
1575
let ( float_ty, int_ty, vector_length) = if self . cx . type_kind ( src_ty) == TypeKind :: Vector {
0 commit comments