@@ -5,6 +5,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
5
5
use rustc_codegen_ssa:: traits:: { AsmBuilderMethods , AsmMethods , BaseTypeMethods , BuilderMethods , GlobalAsmOperandRef , InlineAsmOperandRef } ;
6
6
7
7
use rustc_middle:: { bug, ty:: Instance } ;
8
+ use rustc_middle:: ty:: layout:: TyAndLayout ;
8
9
use rustc_span:: Span ;
9
10
use rustc_target:: asm:: * ;
10
11
@@ -155,7 +156,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
155
156
InlineAsmOperandRef :: Out { reg, late, place } => {
156
157
use ConstraintOrRegister :: * ;
157
158
158
- let ( constraint, ty) = match ( reg_to_gcc ( reg) , place) {
159
+ let constraint = reg_to_gcc ( reg, place. map ( |p| p. layout ) . as_ref ( ) ) ;
160
+ let ( constraint, ty) = match ( constraint, place) {
159
161
( Constraint ( constraint) , Some ( place) ) => ( constraint, place. layout . gcc_type ( self . cx ) ) ,
160
162
// When `reg` is a class and not an explicit register but the out place is not specified,
161
163
// we need to create an unused output variable to assign the output to. This var
@@ -197,7 +199,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
197
199
}
198
200
199
201
InlineAsmOperandRef :: In { reg, value } => {
200
- if let ConstraintOrRegister :: Constraint ( constraint) = reg_to_gcc ( reg) {
202
+ if let ConstraintOrRegister :: Constraint ( constraint) = reg_to_gcc ( reg, None ) {
201
203
inputs. push ( AsmInOperand {
202
204
constraint : Cow :: Borrowed ( constraint) ,
203
205
rust_idx,
@@ -211,7 +213,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
211
213
}
212
214
213
215
InlineAsmOperandRef :: InOut { reg, late, in_value, out_place } => {
214
- let constraint = if let ConstraintOrRegister :: Constraint ( constraint) = reg_to_gcc ( reg) {
216
+ let layout = if let Some ( ref out_place) = out_place {
217
+ & out_place. layout
218
+ } else {
219
+ & in_value. layout
220
+ } ;
221
+ let constraint = if let ConstraintOrRegister :: Constraint ( constraint) = reg_to_gcc ( reg, Some ( layout) ) {
215
222
constraint
216
223
}
217
224
else {
@@ -276,7 +283,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
276
283
match * op {
277
284
// `out("explicit register") var`
278
285
InlineAsmOperandRef :: Out { reg, late, place } => {
279
- if let ConstraintOrRegister :: Register ( reg_name) = reg_to_gcc ( reg) {
286
+ if let ConstraintOrRegister :: Register ( reg_name) = reg_to_gcc ( reg, place . map ( |p| p . layout ) . as_ref ( ) ) {
280
287
let out_place = if let Some ( place) = place {
281
288
place
282
289
}
@@ -304,7 +311,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
304
311
305
312
// `in("explicit register") var`
306
313
InlineAsmOperandRef :: In { reg, value } => {
307
- if let ConstraintOrRegister :: Register ( reg_name) = reg_to_gcc ( reg) {
314
+ if let ConstraintOrRegister :: Register ( reg_name) = reg_to_gcc ( reg, None ) {
308
315
let ty = value. layout . gcc_type ( self . cx ) ;
309
316
let reg_var = self . current_func ( ) . new_local ( None , ty, "input_register" ) ;
310
317
reg_var. set_register_name ( reg_name) ;
@@ -322,7 +329,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
322
329
323
330
// `inout("explicit register") in_var => out_var`
324
331
InlineAsmOperandRef :: InOut { reg, late, in_value, out_place } => {
325
- if let ConstraintOrRegister :: Register ( reg_name) = reg_to_gcc ( reg) {
332
+ let layout = if let Some ( ref out_place) = out_place {
333
+ & out_place. layout
334
+ } else {
335
+ & in_value. layout
336
+ } ;
337
+ if let ConstraintOrRegister :: Register ( reg_name) = reg_to_gcc ( reg, Some ( & layout) ) {
326
338
// See explanation in the first pass.
327
339
let ty = in_value. layout . gcc_type ( self . cx ) ;
328
340
let tmp_var = self . current_func ( ) . new_local ( None , ty, "output_register" ) ;
@@ -544,7 +556,7 @@ fn estimate_template_length(template: &[InlineAsmTemplatePiece], constants_len:
544
556
}
545
557
546
558
/// Converts a register class to a GCC constraint code.
547
- fn reg_to_gcc ( reg : InlineAsmRegOrRegClass ) -> ConstraintOrRegister {
559
+ fn reg_to_gcc ( reg : InlineAsmRegOrRegClass , layout : Option < & TyAndLayout < ' _ > > ) -> ConstraintOrRegister {
548
560
let constraint = match reg {
549
561
// For vector registers LLVM wants the register name to match the type size.
550
562
InlineAsmRegOrRegClass :: Reg ( reg) => {
@@ -564,56 +576,77 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
564
576
_ => unimplemented ! ( ) ,
565
577
}
566
578
} ,
579
+ // They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
567
580
InlineAsmRegOrRegClass :: RegClass ( reg) => match reg {
568
- InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => unimplemented ! ( ) ,
569
- InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: reg) => unimplemented ! ( ) ,
570
- InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) => unimplemented ! ( ) ,
571
- InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => unimplemented ! ( ) ,
572
- InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg) => unimplemented ! ( ) ,
581
+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: reg) => {
582
+ match layout. map ( |l| l. size . bytes ( ) ) {
583
+ Some ( 64 ) => "L" ,
584
+ _ => "K" , // we default to `K` which is a 32 bits register.
585
+ }
586
+ }
587
+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg) => "w" ,
588
+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: vreg_low16) => "x" ,
589
+ InlineAsmRegClass :: AArch64 ( AArch64InlineAsmRegClass :: preg) => {
590
+ unreachable ! ( "clobber-only" )
591
+ }
592
+ InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: reg) => "r" ,
573
593
InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg)
574
594
| InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: dreg_low16)
575
- | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: qreg_low8) => unimplemented ! ( ) ,
576
- InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg_low16)
595
+ | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: qreg_low8)
596
+ | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: sreg_low16)
577
597
| InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: dreg_low8)
578
- | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: qreg_low4) => unimplemented ! ( ) ,
579
- InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: dreg)
580
- | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: qreg) => unimplemented ! ( ) ,
581
- InlineAsmRegClass :: Avr ( _) => unimplemented ! ( ) ,
582
- InlineAsmRegClass :: Bpf ( _) => unimplemented ! ( ) ,
583
- InlineAsmRegClass :: Hexagon ( HexagonInlineAsmRegClass :: reg) => unimplemented ! ( ) ,
584
- InlineAsmRegClass :: Mips ( MipsInlineAsmRegClass :: reg) => unimplemented ! ( ) ,
585
- InlineAsmRegClass :: Mips ( MipsInlineAsmRegClass :: freg) => unimplemented ! ( ) ,
586
- InlineAsmRegClass :: Msp430 ( _) => unimplemented ! ( ) ,
587
- InlineAsmRegClass :: Nvptx ( NvptxInlineAsmRegClass :: reg16) => unimplemented ! ( ) ,
588
- InlineAsmRegClass :: Nvptx ( NvptxInlineAsmRegClass :: reg32) => unimplemented ! ( ) ,
589
- InlineAsmRegClass :: Nvptx ( NvptxInlineAsmRegClass :: reg64) => unimplemented ! ( ) ,
590
- InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: reg) => unimplemented ! ( ) ,
591
- InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: reg_nonzero) => unimplemented ! ( ) ,
592
- InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: freg) => unimplemented ! ( ) ,
598
+ | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: qreg_low4)
599
+ | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: dreg)
600
+ | InlineAsmRegClass :: Arm ( ArmInlineAsmRegClass :: qreg) => "t" ,
601
+ InlineAsmRegClass :: Avr ( AvrInlineAsmRegClass :: reg) => "r" ,
602
+ InlineAsmRegClass :: Avr ( AvrInlineAsmRegClass :: reg_upper) => "d" ,
603
+ InlineAsmRegClass :: Avr ( AvrInlineAsmRegClass :: reg_pair) => "r" ,
604
+ InlineAsmRegClass :: Avr ( AvrInlineAsmRegClass :: reg_iw) => "w" ,
605
+ InlineAsmRegClass :: Avr ( AvrInlineAsmRegClass :: reg_ptr) => "e" ,
606
+ InlineAsmRegClass :: Bpf ( BpfInlineAsmRegClass :: reg) => "r" ,
607
+ InlineAsmRegClass :: Bpf ( BpfInlineAsmRegClass :: wreg) => "w" ,
608
+ InlineAsmRegClass :: Hexagon ( HexagonInlineAsmRegClass :: reg) => "r" ,
609
+ InlineAsmRegClass :: Mips ( MipsInlineAsmRegClass :: reg) => "d" , // more specific than "r"
610
+ InlineAsmRegClass :: Mips ( MipsInlineAsmRegClass :: freg) => "f" ,
611
+ InlineAsmRegClass :: Msp430 ( Msp430InlineAsmRegClass :: reg) => "r" ,
612
+ // For the NVPTX target, could only find the information from LLVM at
613
+ // https://llvm.org/docs/LangRef.html#supported-constraint-code-list so they might be
614
+ // incorrect.
615
+ InlineAsmRegClass :: Nvptx ( NvptxInlineAsmRegClass :: reg16) => "h" ,
616
+ InlineAsmRegClass :: Nvptx ( NvptxInlineAsmRegClass :: reg32) => "r" ,
617
+ InlineAsmRegClass :: Nvptx ( NvptxInlineAsmRegClass :: reg64) => "l" ,
618
+
619
+ InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: reg) => "r" ,
620
+ InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: reg_nonzero) => "b" ,
621
+ InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: freg) => "f" ,
593
622
InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: cr)
594
623
| InlineAsmRegClass :: PowerPC ( PowerPCInlineAsmRegClass :: xer) => {
595
624
unreachable ! ( "clobber-only" )
596
625
} ,
597
- InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg) => unimplemented ! ( ) ,
598
- InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => unimplemented ! ( ) ,
599
- InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => unimplemented ! ( ) ,
626
+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: reg) => "r" ,
627
+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: freg) => "f" ,
628
+ InlineAsmRegClass :: RiscV ( RiscVInlineAsmRegClass :: vreg) => {
629
+ unreachable ! ( "clobber-only" )
630
+ }
600
631
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg) => "r" ,
601
632
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_abcd) => "Q" ,
602
633
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: reg_byte) => "q" ,
603
634
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: xmm_reg)
604
635
| InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: ymm_reg) => "x" ,
605
636
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: zmm_reg) => "v" ,
606
637
InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg) => "Yk" ,
607
- InlineAsmRegClass :: X86 ( X86InlineAsmRegClass :: kreg0) => unimplemented ! ( ) ,
608
- InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => unimplemented ! ( ) ,
609
638
InlineAsmRegClass :: X86 (
610
- X86InlineAsmRegClass :: x87_reg | X86InlineAsmRegClass :: mmx_reg | X86InlineAsmRegClass :: tmm_reg,
639
+ X86InlineAsmRegClass :: kreg0
640
+ | X86InlineAsmRegClass :: x87_reg
641
+ | X86InlineAsmRegClass :: mmx_reg
642
+ | X86InlineAsmRegClass :: tmm_reg,
611
643
) => unreachable ! ( "clobber-only" ) ,
612
644
InlineAsmRegClass :: SpirV ( SpirVInlineAsmRegClass :: reg) => {
613
645
bug ! ( "GCC backend does not support SPIR-V" )
614
646
}
615
- InlineAsmRegClass :: S390x ( S390xInlineAsmRegClass :: reg) => unimplemented ! ( ) ,
616
- InlineAsmRegClass :: S390x ( S390xInlineAsmRegClass :: freg) => unimplemented ! ( ) ,
647
+ InlineAsmRegClass :: Wasm ( WasmInlineAsmRegClass :: local) => "r" ,
648
+ InlineAsmRegClass :: S390x ( S390xInlineAsmRegClass :: reg) => "r" ,
649
+ InlineAsmRegClass :: S390x ( S390xInlineAsmRegClass :: freg) => "f" ,
617
650
InlineAsmRegClass :: Err => unreachable ! ( ) ,
618
651
}
619
652
} ;
0 commit comments