2
2
use crate :: maybe_pqp_cg_ssa as rustc_codegen_ssa;
3
3
4
4
use super :: Builder ;
5
+ use crate :: abi:: ConvSpirvType ;
5
6
use crate :: builder_spirv:: { BuilderCursor , SpirvValue } ;
6
7
use crate :: codegen_cx:: CodegenCx ;
7
8
use crate :: spirv_type:: SpirvType ;
@@ -12,13 +13,18 @@ use rspirv::spirv::{
12
13
GroupOperation , ImageOperands , KernelProfilingInfo , LoopControl , MemoryAccess , MemorySemantics ,
13
14
Op , RayFlags , SelectionControl , StorageClass , Word ,
14
15
} ;
16
+ use rustc_abi:: { BackendRepr , Primitive } ;
15
17
use rustc_ast:: ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
18
+ use rustc_codegen_ssa:: mir:: operand:: OperandValue ;
16
19
use rustc_codegen_ssa:: mir:: place:: PlaceRef ;
17
- use rustc_codegen_ssa:: traits:: { AsmBuilderMethods , InlineAsmOperandRef } ;
20
+ use rustc_codegen_ssa:: traits:: {
21
+ AsmBuilderMethods , BackendTypes , BuilderMethods , InlineAsmOperandRef ,
22
+ } ;
18
23
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
19
24
use rustc_middle:: { bug, ty:: Instance } ;
20
25
use rustc_span:: { DUMMY_SP , Span } ;
21
26
use rustc_target:: asm:: { InlineAsmRegClass , InlineAsmRegOrRegClass , SpirVInlineAsmRegClass } ;
27
+ use smallvec:: SmallVec ;
22
28
23
29
pub struct InstructionTable {
24
30
table : FxHashMap < & ' static str , & ' static rspirv:: grammar:: Instruction < ' static > > ,
@@ -33,6 +39,35 @@ impl InstructionTable {
33
39
}
34
40
}
35
41
42
+ // HACK(eddyb) `InlineAsmOperandRef` lacks `#[derive(Clone)]`
43
+ fn inline_asm_operand_ref_clone < ' tcx , B : BackendTypes + ?Sized > (
44
+ operand : & InlineAsmOperandRef < ' tcx , B > ,
45
+ ) -> InlineAsmOperandRef < ' tcx , B > {
46
+ use InlineAsmOperandRef :: * ;
47
+
48
+ match operand {
49
+ & In { reg, value } => In { reg, value } ,
50
+ & Out { reg, late, place } => Out { reg, late, place } ,
51
+ & InOut {
52
+ reg,
53
+ late,
54
+ in_value,
55
+ out_place,
56
+ } => InOut {
57
+ reg,
58
+ late,
59
+ in_value,
60
+ out_place,
61
+ } ,
62
+ Const { string } => Const {
63
+ string : string. clone ( ) ,
64
+ } ,
65
+ & SymFn { instance } => SymFn { instance } ,
66
+ & SymStatic { def_id } => SymStatic { def_id } ,
67
+ & Label { label } => Label { label } ,
68
+ }
69
+ }
70
+
36
71
impl < ' a , ' tcx > AsmBuilderMethods < ' tcx > for Builder < ' a , ' tcx > {
37
72
/* Example asm and the template it compiles to:
38
73
asm!(
@@ -70,6 +105,45 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
70
105
if !unsupported_options. is_empty ( ) {
71
106
self . err ( format ! ( "asm flags not supported: {unsupported_options:?}" ) ) ;
72
107
}
108
+
109
+ // HACK(eddyb) get more accurate pointers types, for pointer operands,
110
+ // from the Rust types available in their respective `OperandRef`s.
111
+ let mut operands: SmallVec < [ _ ; 8 ] > =
112
+ operands. iter ( ) . map ( inline_asm_operand_ref_clone) . collect ( ) ;
113
+ for operand in & mut operands {
114
+ let ( in_value, out_place) = match operand {
115
+ InlineAsmOperandRef :: In { value, .. } => ( Some ( value) , None ) ,
116
+ InlineAsmOperandRef :: InOut {
117
+ in_value,
118
+ out_place,
119
+ ..
120
+ } => ( Some ( in_value) , out_place. as_mut ( ) ) ,
121
+ InlineAsmOperandRef :: Out { place, .. } => ( None , place. as_mut ( ) ) ,
122
+
123
+ InlineAsmOperandRef :: Const { .. }
124
+ | InlineAsmOperandRef :: SymFn { .. }
125
+ | InlineAsmOperandRef :: SymStatic { .. }
126
+ | InlineAsmOperandRef :: Label { .. } => ( None , None ) ,
127
+ } ;
128
+
129
+ if let Some ( in_value) = in_value {
130
+ if let ( BackendRepr :: Scalar ( scalar) , OperandValue :: Immediate ( in_value_spv) ) =
131
+ ( in_value. layout . backend_repr , & mut in_value. val )
132
+ {
133
+ if let Primitive :: Pointer ( _) = scalar. primitive ( ) {
134
+ let in_value_precise_type = in_value. layout . spirv_type ( self . span ( ) , self ) ;
135
+ * in_value_spv = self . pointercast ( * in_value_spv, in_value_precise_type) ;
136
+ }
137
+ }
138
+ }
139
+ if let Some ( out_place) = out_place {
140
+ let out_place_precise_type = out_place. layout . spirv_type ( self . span ( ) , self ) ;
141
+ let out_place_precise_ptr_type = self . type_ptr_to ( out_place_precise_type) ;
142
+ out_place. val . llval =
143
+ self . pointercast ( out_place. val . llval , out_place_precise_ptr_type) ;
144
+ }
145
+ }
146
+
73
147
// vec of lines, and each line is vec of tokens
74
148
let mut tokens = vec ! [ vec![ ] ] ;
75
149
for piece in template {
@@ -131,7 +205,7 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
131
205
let mut id_map = FxHashMap :: default ( ) ;
132
206
let mut defined_ids = FxHashSet :: default ( ) ;
133
207
let mut id_to_type_map = FxHashMap :: default ( ) ;
134
- for operand in operands {
208
+ for operand in & operands {
135
209
if let InlineAsmOperandRef :: In { reg : _, value } = operand {
136
210
let value = value. immediate ( ) ;
137
211
id_to_type_map. insert ( value. def ( self ) , value. ty ) ;
0 commit comments