@@ -31,12 +31,151 @@ 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
+ #[ must_use]
42
+ pub ( crate ) struct SBuilder < ' a , ' ll > {
43
+ pub llbuilder : & ' ll mut llvm:: Builder < ' ll > ,
44
+ pub cx : & ' a SimpleCx < ' ll > ,
45
+ }
46
+
47
+ impl Drop for SBuilder < ' _ , ' _ > {
48
+ fn drop ( & mut self ) {
49
+ unsafe {
50
+ llvm:: LLVMDisposeBuilder ( & mut * ( self . llbuilder as * mut _ ) ) ;
51
+ }
52
+ }
53
+ }
54
+
55
+ impl < ' a , ' ll > SBuilder < ' a , ' ll > {
56
+ fn build ( cx : & ' a SimpleCx < ' ll > , llbb : & ' ll BasicBlock ) -> SBuilder < ' a , ' ll > {
57
+ let bx = SBuilder :: with_scx ( cx) ;
58
+ unsafe {
59
+ llvm:: LLVMPositionBuilderAtEnd ( bx. llbuilder , llbb) ;
60
+ }
61
+ bx
62
+ }
63
+ }
64
+
65
+ impl < ' a , ' ll > SBuilder < ' a , ' ll > {
66
+ fn with_scx ( scx : & ' a SimpleCx < ' ll > ) -> Self {
67
+ // Create a fresh builder from the simple context.
68
+ let llbuilder = unsafe { llvm:: LLVMCreateBuilderInContext ( scx. llcx ) } ;
69
+ SBuilder { llbuilder, cx : scx }
70
+ }
71
+
72
+ pub ( crate ) fn bitcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
73
+ unsafe { llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, UNNAMED ) }
74
+ }
75
+
76
+ fn ret_void ( & mut self ) {
77
+ unsafe {
78
+ llvm:: LLVMBuildRetVoid ( self . llbuilder ) ;
79
+ }
80
+ }
81
+
82
+ fn ret ( & mut self , v : & ' ll Value ) {
83
+ unsafe {
84
+ llvm:: LLVMBuildRet ( self . llbuilder , v) ;
85
+ }
86
+ }
87
+
88
+ fn check_call < ' b > (
89
+ & mut self ,
90
+ typ : & str ,
91
+ fn_ty : & ' ll Type ,
92
+ llfn : & ' ll Value ,
93
+ args : & ' b [ & ' ll Value ] ,
94
+ ) -> Cow < ' b , [ & ' ll Value ] > {
95
+ assert ! (
96
+ self . cx. type_kind( fn_ty) == TypeKind :: Function ,
97
+ "builder::{typ} not passed a function, but {fn_ty:?}"
98
+ ) ;
99
+
100
+ let param_tys = self . cx . func_params_types ( fn_ty) ;
101
+
102
+ let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
103
+ . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
104
+
105
+ if all_args_match {
106
+ return Cow :: Borrowed ( args) ;
107
+ }
108
+
109
+ let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
110
+ . enumerate ( )
111
+ . map ( |( i, ( expected_ty, & actual_val) ) | {
112
+ let actual_ty = self . cx . val_ty ( actual_val) ;
113
+ if expected_ty != actual_ty {
114
+ debug ! (
115
+ "type mismatch in function call of {:?}. \
116
+ Expected {:?} for param {}, got {:?}; injecting bitcast",
117
+ llfn, expected_ty, i, actual_ty
118
+ ) ;
119
+ self . bitcast ( actual_val, expected_ty)
120
+ } else {
121
+ actual_val
122
+ }
123
+ } )
124
+ . collect ( ) ;
125
+
126
+ Cow :: Owned ( casted_args)
127
+ }
128
+
129
+ fn call (
130
+ & mut self ,
131
+ llty : & ' ll Type ,
132
+ //fn_attrs: Option<&CodegenFnAttrs>,
133
+ //fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
134
+ llfn : & ' ll Value ,
135
+ args : & [ & ' ll Value ] ,
136
+ funclet : Option < & Funclet < ' ll > > ,
137
+ //instance: Option<Instance<'tcx>>,
138
+ ) -> & ' ll Value {
139
+ debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
140
+
141
+ let args = self . check_call ( "call" , llty, llfn, args) ;
142
+ let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
143
+ let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
144
+ if let Some ( funclet_bundle) = funclet_bundle {
145
+ bundles. push ( funclet_bundle) ;
146
+ }
147
+
148
+ // Emit CFI pointer type membership test
149
+ //self.cfi_type_test(fn_attrs, fn_abi, instance, llfn);
150
+
151
+ // Emit KCFI operand bundle
152
+ //let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
153
+ //if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
154
+ // bundles.push(kcfi_bundle);
155
+ //}
156
+
157
+ let call = unsafe {
158
+ llvm:: LLVMBuildCallWithOperandBundles (
159
+ self . llbuilder ,
160
+ llty,
161
+ llfn,
162
+ args. as_ptr ( ) as * const & llvm:: Value ,
163
+ args. len ( ) as c_uint ,
164
+ bundles. as_ptr ( ) ,
165
+ bundles. len ( ) as c_uint ,
166
+ c"" . as_ptr ( ) ,
167
+ )
168
+ } ;
169
+ //if let Some(fn_abi) = fn_abi {
170
+ // fn_abi.apply_attrs_callsite(self, call);
171
+ //}
172
+ call
173
+ }
174
+
175
+ }
176
+
177
+
178
+
40
179
// All Builders must have an llfn associated with them
41
180
#[ must_use]
42
181
pub ( crate ) struct Builder < ' a , ' ll , ' tcx > {
@@ -55,7 +194,7 @@ impl Drop for Builder<'_, '_, '_> {
55
194
/// Empty string, to be used where LLVM expects an instruction name, indicating
56
195
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
57
196
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
58
- const UNNAMED : * const c_char = c"" . as_ptr ( ) ;
197
+ pub ( crate ) const UNNAMED : * const c_char = c"" . as_ptr ( ) ;
59
198
60
199
impl < ' ll , ' tcx > BackendTypes for Builder < ' _ , ' ll , ' tcx > {
61
200
type Value = <CodegenCx < ' ll , ' tcx > as BackendTypes >:: Value ;
@@ -170,7 +309,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
170
309
fn append_block ( cx : & ' a CodegenCx < ' ll , ' tcx > , llfn : & ' ll Value , name : & str ) -> & ' ll BasicBlock {
171
310
unsafe {
172
311
let name = SmallCStr :: new ( name) ;
173
- llvm:: LLVMAppendBasicBlockInContext ( cx. llcx , llfn, name. as_ptr ( ) )
312
+ llvm:: LLVMAppendBasicBlockInContext ( cx. scx . llcx , llfn, name. as_ptr ( ) )
174
313
}
175
314
}
176
315
@@ -621,14 +760,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
621
760
llvm:: LLVMValueAsMetadata ( self . cx . const_uint_big ( llty, range. start ) ) ,
622
761
llvm:: LLVMValueAsMetadata ( self . cx . const_uint_big ( llty, range. end . wrapping_add ( 1 ) ) ) ,
623
762
] ;
624
- let md = llvm:: LLVMMDNodeInContext2 ( self . cx . llcx , md. as_ptr ( ) , md. len ( ) ) ;
763
+ let md = llvm:: LLVMMDNodeInContext2 ( self . cx . scx . llcx , md. as_ptr ( ) , md. len ( ) ) ;
625
764
self . set_metadata ( load, llvm:: MD_range , md) ;
626
765
}
627
766
}
628
767
629
768
fn nonnull_metadata ( & mut self , load : & ' ll Value ) {
630
769
unsafe {
631
- let md = llvm:: LLVMMDNodeInContext2 ( self . cx . llcx , ptr:: null ( ) , 0 ) ;
770
+ let md = llvm:: LLVMMDNodeInContext2 ( self . cx . scx . llcx , ptr:: null ( ) , 0 ) ;
632
771
self . set_metadata ( load, llvm:: MD_nonnull , md) ;
633
772
}
634
773
}
@@ -678,7 +817,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
678
817
//
679
818
// [1]: https://llvm.org/docs/LangRef.html#store-instruction
680
819
let one = llvm:: LLVMValueAsMetadata ( self . cx . const_i32 ( 1 ) ) ;
681
- let md = llvm:: LLVMMDNodeInContext2 ( self . cx . llcx , & one, 1 ) ;
820
+ let md = llvm:: LLVMMDNodeInContext2 ( self . cx . scx . llcx , & one, 1 ) ;
682
821
self . set_metadata ( store, llvm:: MD_nontemporal , md) ;
683
822
}
684
823
}
@@ -1144,7 +1283,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1144
1283
1145
1284
fn set_invariant_load ( & mut self , load : & ' ll Value ) {
1146
1285
unsafe {
1147
- let md = llvm:: LLVMMDNodeInContext2 ( self . cx . llcx , ptr:: null ( ) , 0 ) ;
1286
+ let md = llvm:: LLVMMDNodeInContext2 ( self . cx . scx . llcx , ptr:: null ( ) , 0 ) ;
1148
1287
self . set_metadata ( load, llvm:: MD_invariant_load , md) ;
1149
1288
}
1150
1289
}
@@ -1209,7 +1348,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1209
1348
1210
1349
fn apply_attrs_to_cleanup_callsite ( & mut self , llret : & ' ll Value ) {
1211
1350
// Cleanup is always the cold path.
1212
- let cold_inline = llvm:: AttributeKind :: Cold . create_attr ( self . llcx ) ;
1351
+ let cold_inline = llvm:: AttributeKind :: Cold . create_attr ( self . scx . llcx ) ;
1213
1352
attributes:: apply_to_callsite ( llret, llvm:: AttributePlace :: Function , & [ cold_inline] ) ;
1214
1353
}
1215
1354
}
@@ -1224,7 +1363,7 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
1224
1363
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1225
1364
fn with_cx ( cx : & ' a CodegenCx < ' ll , ' tcx > ) -> Self {
1226
1365
// Create a fresh builder from the crate context.
1227
- let llbuilder = unsafe { llvm:: LLVMCreateBuilderInContext ( cx. llcx ) } ;
1366
+ let llbuilder = unsafe { llvm:: LLVMCreateBuilderInContext ( cx. scx . llcx ) } ;
1228
1367
Builder { llbuilder, cx }
1229
1368
}
1230
1369
@@ -1241,21 +1380,21 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1241
1380
fn align_metadata ( & mut self , load : & ' ll Value , align : Align ) {
1242
1381
unsafe {
1243
1382
let md = [ llvm:: LLVMValueAsMetadata ( self . cx . const_u64 ( align. bytes ( ) ) ) ] ;
1244
- let md = llvm:: LLVMMDNodeInContext2 ( self . cx . llcx , md. as_ptr ( ) , md. len ( ) ) ;
1383
+ let md = llvm:: LLVMMDNodeInContext2 ( self . cx . scx . llcx , md. as_ptr ( ) , md. len ( ) ) ;
1245
1384
self . set_metadata ( load, llvm:: MD_align , md) ;
1246
1385
}
1247
1386
}
1248
1387
1249
1388
fn noundef_metadata ( & mut self , load : & ' ll Value ) {
1250
1389
unsafe {
1251
- let md = llvm:: LLVMMDNodeInContext2 ( self . cx . llcx , ptr:: null ( ) , 0 ) ;
1390
+ let md = llvm:: LLVMMDNodeInContext2 ( self . cx . scx . llcx , ptr:: null ( ) , 0 ) ;
1252
1391
self . set_metadata ( load, llvm:: MD_noundef , md) ;
1253
1392
}
1254
1393
}
1255
1394
1256
1395
pub ( crate ) fn set_unpredictable ( & mut self , inst : & ' ll Value ) {
1257
1396
unsafe {
1258
- let md = llvm:: LLVMMDNodeInContext2 ( self . cx . llcx , ptr:: null ( ) , 0 ) ;
1397
+ let md = llvm:: LLVMMDNodeInContext2 ( self . cx . scx . llcx , ptr:: null ( ) , 0 ) ;
1259
1398
self . set_metadata ( inst, llvm:: MD_unpredictable , md) ;
1260
1399
}
1261
1400
}
0 commit comments