11use std:: borrow:: Cow ;
22
3- use gccjit:: { LValue , RValue , ToRValue , Type } ;
3+ use gccjit:: { GlobalKind , LValue , RValue , ToRValue , Type } ;
44use rustc_ast:: ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
55use rustc_codegen_ssa:: mir:: operand:: OperandValue ;
66use rustc_codegen_ssa:: mir:: place:: PlaceRef ;
77use rustc_codegen_ssa:: traits:: {
88 AsmBuilderMethods , AsmCodegenMethods , BaseTypeCodegenMethods , BuilderMethods ,
99 GlobalAsmOperandRef , InlineAsmOperandRef ,
1010} ;
11- use rustc_middle:: bug;
1211use rustc_middle:: ty:: Instance ;
12+ use rustc_middle:: { bug, mir} ;
1313use rustc_span:: Span ;
1414use rustc_target:: asm:: * ;
1515
@@ -827,6 +827,98 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
827827 let att_dialect = matches ! ( asm_arch, InlineAsmArch :: X86 | InlineAsmArch :: X86_64 )
828828 && options. contains ( InlineAsmOptions :: ATT_SYNTAX ) ;
829829
830+ // Convert all operands to string interpolations
831+ let converted_operands = operands
832+ . iter ( )
833+ . enumerate ( )
834+ . map ( |( operand_idx, operand) | {
835+ match * operand {
836+ GlobalAsmOperandRef :: Interpolate { ref string } => {
837+ // Const operands get injected directly into the
838+ // template. Note that we don't need to escape $
839+ // here unlike normal inline assembly.
840+ string. to_owned ( )
841+ }
842+ GlobalAsmOperandRef :: ConstPointer { value, instance } => {
843+ let ( prov, offset) = value. into_parts ( ) ;
844+ let global_alloc = self . tcx . global_alloc ( prov. alloc_id ( ) ) ;
845+ let symbol = ' sym: {
846+ let alloc = match global_alloc {
847+ mir:: interpret:: GlobalAlloc :: Function { instance } => {
848+ let function = get_fn ( self , instance) ;
849+ self . add_used_function ( function) ;
850+ // TODO(@Amanieu): Additional mangling is needed on
851+ // some targets to add a leading underscore (Mach-O)
852+ // or byte count suffixes (x86 Windows).
853+ break ' sym self . tcx . symbol_name ( instance) . name . to_owned ( ) ;
854+ }
855+ mir:: interpret:: GlobalAlloc :: VTable ( ty, dyn_ty) => self
856+ . tcx
857+ . global_alloc ( self . tcx . vtable_allocation ( (
858+ ty,
859+ dyn_ty. principal ( ) . map ( |principal| {
860+ self . tcx
861+ . instantiate_bound_regions_with_erased ( principal)
862+ } ) ,
863+ ) ) )
864+ . unwrap_memory ( ) ,
865+ mir:: interpret:: GlobalAlloc :: Static ( def_id) => {
866+ // TODO(antoyo): set the global variable as used.
867+ // TODO(@Amanieu): Additional mangling is needed on
868+ // some targets to add a leading underscore (Mach-O).
869+ let instance = Instance :: mono ( self . tcx , def_id) ;
870+ break ' sym self . tcx . symbol_name ( instance) . name . to_owned ( ) ;
871+ }
872+ mir:: interpret:: GlobalAlloc :: Memory ( alloc) => alloc,
873+ } ;
874+
875+ // For ZSTs directly codegen an aligned pointer.
876+ if alloc. inner ( ) . len ( ) == 0 {
877+ assert_eq ! ( offset. bytes( ) , 0 ) ;
878+ return format ! ( "{}" , alloc. inner( ) . align. bytes( ) ) ;
879+ }
880+
881+ let asm_name = self . tcx . symbol_name ( instance) ;
882+ let sym_name = format ! ( "{asm_name}.{operand_idx}" ) ;
883+
884+ let init = crate :: consts:: const_alloc_to_gcc ( self , alloc) ;
885+ let alloc = alloc. inner ( ) ;
886+ let typ = self . val_ty ( init) . get_aligned ( alloc. align . bytes ( ) ) ;
887+
888+ let global = self . declare_global_with_linkage (
889+ & sym_name,
890+ typ,
891+ GlobalKind :: Exported ,
892+ ) ;
893+ global. global_set_initializer_rvalue ( init) ;
894+ // TODO(nbdd0121): set unnamed address.
895+ // TODO(nbdd0121): set the global variable as used.
896+
897+ sym_name
898+ } ;
899+
900+ let offset = offset. bytes ( ) ;
901+ if offset != 0 { format ! ( "{symbol}+{offset}" ) } else { symbol }
902+ }
903+ GlobalAsmOperandRef :: SymFn { instance } => {
904+ let function = get_fn ( self , instance) ;
905+ self . add_used_function ( function) ;
906+ // TODO(@Amanieu): Additional mangling is needed on
907+ // some targets to add a leading underscore (Mach-O)
908+ // or byte count suffixes (x86 Windows).
909+ self . tcx . symbol_name ( instance) . name . to_owned ( )
910+ }
911+ GlobalAsmOperandRef :: SymStatic { def_id } => {
912+ // TODO(antoyo): set the global variable as used.
913+ // TODO(@Amanieu): Additional mangling is needed on
914+ // some targets to add a leading underscore (Mach-O).
915+ let instance = Instance :: mono ( self . tcx , def_id) ;
916+ self . tcx . symbol_name ( instance) . name . to_owned ( )
917+ }
918+ }
919+ } )
920+ . collect :: < Vec < _ > > ( ) ;
921+
830922 // Build the template string
831923 let mut template_str = ".pushsection .text\n " . to_owned ( ) ;
832924 if att_dialect {
@@ -850,33 +942,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
850942 }
851943 }
852944 InlineAsmTemplatePiece :: Placeholder { operand_idx, modifier : _, span : _ } => {
853- match operands[ operand_idx] {
854- GlobalAsmOperandRef :: Interpolate { ref string } => {
855- // Const operands get injected directly into the
856- // template. Note that we don't need to escape %
857- // here unlike normal inline assembly.
858- template_str. push_str ( string) ;
859- }
860-
861- GlobalAsmOperandRef :: SymFn { instance } => {
862- let function = get_fn ( self , instance) ;
863- self . add_used_function ( function) ;
864- // TODO(@Amanieu): Additional mangling is needed on
865- // some targets to add a leading underscore (Mach-O)
866- // or byte count suffixes (x86 Windows).
867- let name = self . tcx . symbol_name ( instance) . name ;
868- template_str. push_str ( name) ;
869- }
870-
871- GlobalAsmOperandRef :: SymStatic { def_id } => {
872- // TODO(antoyo): set the global variable as used.
873- // TODO(@Amanieu): Additional mangling is needed on
874- // some targets to add a leading underscore (Mach-O).
875- let instance = Instance :: mono ( self . tcx , def_id) ;
876- let name = self . tcx . symbol_name ( instance) . name ;
877- template_str. push_str ( name) ;
878- }
879- }
945+ template_str. push_str ( & converted_operands[ operand_idx] ) ;
880946 }
881947 }
882948 }
0 commit comments