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