@@ -13,6 +13,7 @@ use rustc_ast::ast;
13
13
use rustc_hir:: lang_items;
14
14
use rustc_index:: vec:: Idx ;
15
15
use rustc_middle:: mir;
16
+ use rustc_middle:: mir:: interpret:: { AllocId , ConstValue , Pointer , Scalar } ;
16
17
use rustc_middle:: mir:: AssertKind ;
17
18
use rustc_middle:: ty:: layout:: { FnAbiExt , HasTyCtxt } ;
18
19
use rustc_middle:: ty:: { self , Instance , Ty , TypeFoldable } ;
@@ -821,6 +822,123 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
821
822
cleanup,
822
823
) ;
823
824
}
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
+ }
824
942
}
825
943
826
944
impl < ' 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> {
916
1034
bug ! ( "borrowck false edges in codegen" )
917
1035
}
918
1036
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
+ ) ;
1010
1047
}
1011
1048
}
1012
1049
}
0 commit comments