@@ -13,6 +13,7 @@ use rustc_ast::ast;
1313use rustc_hir:: lang_items;
1414use rustc_index:: vec:: Idx ;
1515use rustc_middle:: mir;
16+ use rustc_middle:: mir:: interpret:: { AllocId , ConstValue , Pointer , Scalar } ;
1617use rustc_middle:: mir:: AssertKind ;
1718use rustc_middle:: ty:: layout:: { FnAbiExt , HasTyCtxt } ;
1819use rustc_middle:: ty:: { self , Instance , Ty , TypeFoldable } ;
@@ -821,6 +822,123 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
821822 cleanup,
822823 ) ;
823824 }
825+
826+ fn codegen_asm_terminator (
827+ & mut self ,
828+ helper : TerminatorCodegenHelper < ' tcx > ,
829+ mut bx : Bx ,
830+ terminator : & mir:: Terminator < ' tcx > ,
831+ template : & [ ast:: InlineAsmTemplatePiece ] ,
832+ operands : & [ mir:: InlineAsmOperand < ' tcx > ] ,
833+ options : ast:: InlineAsmOptions ,
834+ destination : Option < mir:: BasicBlock > ,
835+ ) {
836+ let span = terminator. source_info . span ;
837+
838+ let operands: Vec < _ > = operands
839+ . iter ( )
840+ . map ( |op| match * op {
841+ mir:: InlineAsmOperand :: In { reg, ref value } => {
842+ let value = self . codegen_operand ( & mut bx, value) ;
843+ InlineAsmOperandRef :: In { reg, value }
844+ }
845+ mir:: InlineAsmOperand :: Out { reg, late, ref place } => {
846+ let place = place. map ( |place| self . codegen_place ( & mut bx, place. as_ref ( ) ) ) ;
847+ InlineAsmOperandRef :: Out { reg, late, place }
848+ }
849+ mir:: InlineAsmOperand :: InOut { reg, late, ref in_value, ref out_place } => {
850+ let in_value = self . codegen_operand ( & mut bx, in_value) ;
851+ let out_place =
852+ out_place. map ( |out_place| self . codegen_place ( & mut bx, out_place. as_ref ( ) ) ) ;
853+ InlineAsmOperandRef :: InOut { reg, late, in_value, out_place }
854+ }
855+ mir:: InlineAsmOperand :: Const { ref value } => {
856+ if let mir:: Operand :: Constant ( constant) = value {
857+ let const_value = self
858+ . eval_mir_constant ( constant)
859+ . unwrap_or_else ( |_| span_bug ! ( span, "asm const cannot be resolved" ) ) ;
860+ let ty = constant. literal . ty ;
861+ let size = bx. layout_of ( ty) . size ;
862+ let scalar = match const_value {
863+ // Promoted constants are evaluated into a ByRef instead of a Scalar,
864+ // but we want the scalar value here.
865+ ConstValue :: ByRef { alloc, offset } => {
866+ let ptr = Pointer :: new ( AllocId ( 0 ) , offset) ;
867+ alloc
868+ . read_scalar ( & bx, ptr, size)
869+ . and_then ( |s| s. not_undef ( ) )
870+ . unwrap_or_else ( |e| {
871+ bx. tcx ( ) . sess . span_err (
872+ span,
873+ & format ! ( "Could not evaluate asm const: {}" , e) ,
874+ ) ;
875+
876+ // We are erroring out, just emit a dummy constant.
877+ Scalar :: from_u64 ( 0 )
878+ } )
879+ }
880+ _ => span_bug ! ( span, "expected ByRef for promoted asm const" ) ,
881+ } ;
882+ let value = scalar. assert_bits ( size) ;
883+ let string = match ty. kind {
884+ ty:: Uint ( _) => value. to_string ( ) ,
885+ ty:: Int ( int_ty) => {
886+ match int_ty. normalize ( bx. tcx ( ) . sess . target . ptr_width ) {
887+ ast:: IntTy :: I8 => ( value as i8 ) . to_string ( ) ,
888+ ast:: IntTy :: I16 => ( value as i16 ) . to_string ( ) ,
889+ ast:: IntTy :: I32 => ( value as i32 ) . to_string ( ) ,
890+ ast:: IntTy :: I64 => ( value as i64 ) . to_string ( ) ,
891+ ast:: IntTy :: I128 => ( value as i128 ) . to_string ( ) ,
892+ ast:: IntTy :: Isize => unreachable ! ( ) ,
893+ }
894+ }
895+ ty:: Float ( ast:: FloatTy :: F32 ) => {
896+ f32:: from_bits ( value as u32 ) . to_string ( )
897+ }
898+ ty:: Float ( ast:: FloatTy :: F64 ) => {
899+ f64:: from_bits ( value as u64 ) . to_string ( )
900+ }
901+ _ => span_bug ! ( span, "asm const has bad type {}" , ty) ,
902+ } ;
903+ InlineAsmOperandRef :: Const { string }
904+ } else {
905+ span_bug ! ( span, "asm const is not a constant" ) ;
906+ }
907+ }
908+ mir:: InlineAsmOperand :: SymFn { ref value } => {
909+ let literal = self . monomorphize ( & value. literal ) ;
910+ if let ty:: FnDef ( def_id, substs) = literal. ty . kind {
911+ let instance = ty:: Instance :: resolve (
912+ bx. tcx ( ) ,
913+ ty:: ParamEnv :: reveal_all ( ) ,
914+ def_id,
915+ substs,
916+ )
917+ . unwrap ( )
918+ . unwrap ( ) ;
919+ InlineAsmOperandRef :: SymFn { instance }
920+ } else {
921+ span_bug ! ( span, "invalid type for asm sym (fn)" ) ;
922+ }
923+ }
924+ mir:: InlineAsmOperand :: SymStatic { ref value } => {
925+ if let Some ( def_id) = value. check_static_ptr ( bx. tcx ( ) ) {
926+ InlineAsmOperandRef :: SymStatic { def_id }
927+ } else {
928+ span_bug ! ( span, "invalid type for asm sym (static)" ) ;
929+ }
930+ }
931+ } )
932+ . collect ( ) ;
933+
934+ bx. codegen_inline_asm ( template, & operands, options, span) ;
935+
936+ if let Some ( target) = destination {
937+ helper. funclet_br ( self , & mut bx, target) ;
938+ } else {
939+ bx. unreachable ( ) ;
940+ }
941+ }
824942}
825943
826944impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
@@ -916,97 +1034,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9161034 bug ! ( "borrowck false edges in codegen" )
9171035 }
9181036
919- mir:: TerminatorKind :: InlineAsm { template, ref operands, options, ref destination } => {
920- let span = terminator. source_info . span ;
921-
922- let operands: Vec < _ > = operands
923- . iter ( )
924- . map ( |op| match * op {
925- mir:: InlineAsmOperand :: In { reg, ref value } => {
926- let value = self . codegen_operand ( & mut bx, value) ;
927- InlineAsmOperandRef :: In { reg, value }
928- }
929- mir:: InlineAsmOperand :: Out { reg, late, ref place } => {
930- let place =
931- place. map ( |place| self . codegen_place ( & mut bx, place. as_ref ( ) ) ) ;
932- InlineAsmOperandRef :: Out { reg, late, place }
933- }
934- mir:: InlineAsmOperand :: InOut { reg, late, ref in_value, ref out_place } => {
935- let in_value = self . codegen_operand ( & mut bx, in_value) ;
936- let out_place = out_place
937- . map ( |out_place| self . codegen_place ( & mut bx, out_place. as_ref ( ) ) ) ;
938- InlineAsmOperandRef :: InOut { reg, late, in_value, out_place }
939- }
940- mir:: InlineAsmOperand :: Const { ref value } => {
941- if let mir:: Operand :: Constant ( constant) = value {
942- let const_value =
943- self . eval_mir_constant ( constant) . unwrap_or_else ( |_| {
944- span_bug ! ( span, "asm const cannot be resolved" )
945- } ) ;
946- let ty = constant. literal . ty ;
947- let value = const_value
948- . try_to_bits_for_ty ( bx. tcx ( ) , ty:: ParamEnv :: reveal_all ( ) , ty)
949- . unwrap_or_else ( || {
950- span_bug ! ( span, "asm const has non-scalar value" )
951- } ) ;
952- let string = match ty. kind {
953- ty:: Uint ( _) => value. to_string ( ) ,
954- ty:: Int ( int_ty) => {
955- match int_ty. normalize ( bx. tcx ( ) . sess . target . ptr_width ) {
956- ast:: IntTy :: I8 => ( value as i8 ) . to_string ( ) ,
957- ast:: IntTy :: I16 => ( value as i16 ) . to_string ( ) ,
958- ast:: IntTy :: I32 => ( value as i32 ) . to_string ( ) ,
959- ast:: IntTy :: I64 => ( value as i64 ) . to_string ( ) ,
960- ast:: IntTy :: I128 => ( value as i128 ) . to_string ( ) ,
961- ast:: IntTy :: Isize => unreachable ! ( ) ,
962- }
963- }
964- ty:: Float ( ast:: FloatTy :: F32 ) => {
965- f32:: from_bits ( value as u32 ) . to_string ( )
966- }
967- ty:: Float ( ast:: FloatTy :: F64 ) => {
968- f64:: from_bits ( value as u64 ) . to_string ( )
969- }
970- _ => span_bug ! ( span, "asm const has bad type {}" , ty) ,
971- } ;
972- InlineAsmOperandRef :: Const { string }
973- } else {
974- span_bug ! ( span, "asm const is not a constant" ) ;
975- }
976- }
977- mir:: InlineAsmOperand :: SymFn { ref value } => {
978- let literal = self . monomorphize ( & value. literal ) ;
979- if let ty:: FnDef ( def_id, substs) = literal. ty . kind {
980- let instance = ty:: Instance :: resolve (
981- bx. tcx ( ) ,
982- ty:: ParamEnv :: reveal_all ( ) ,
983- def_id,
984- substs,
985- )
986- . unwrap ( )
987- . unwrap ( ) ;
988- InlineAsmOperandRef :: SymFn { instance }
989- } else {
990- span_bug ! ( span, "invalid type for asm sym (fn)" ) ;
991- }
992- }
993- mir:: InlineAsmOperand :: SymStatic { ref value } => {
994- if let Some ( def_id) = value. check_static_ptr ( bx. tcx ( ) ) {
995- InlineAsmOperandRef :: SymStatic { def_id }
996- } else {
997- span_bug ! ( span, "invalid type for asm sym (static)" ) ;
998- }
999- }
1000- } )
1001- . collect ( ) ;
1002-
1003- bx. codegen_inline_asm ( template, & operands, options, span) ;
1004-
1005- if let Some ( target) = destination {
1006- helper. funclet_br ( self , & mut bx, * target) ;
1007- } else {
1008- bx. unreachable ( ) ;
1009- }
1037+ mir:: TerminatorKind :: InlineAsm { template, ref operands, options, destination } => {
1038+ self . codegen_asm_terminator (
1039+ helper,
1040+ bx,
1041+ terminator,
1042+ template,
1043+ operands,
1044+ options,
1045+ destination,
1046+ ) ;
10101047 }
10111048 }
10121049 }
0 commit comments