@@ -67,7 +67,7 @@ impl<'a, 'll> SBuilder<'a, 'll> {
6767 ) -> & ' ll Value {
6868 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
6969
70- let args = self . check_call ( "call" , llty, llfn, args) ;
70+ let args = self . cast_arguments ( "call" , llty, llfn, args) ;
7171 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
7272 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
7373 if let Some ( funclet_bundle) = funclet_bundle {
@@ -97,10 +97,89 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
9797 GenericBuilder { llbuilder, cx : scx }
9898 }
9999
100+ pub ( crate ) fn declare_intrinsic (
101+ & mut self ,
102+ intrinsic : llvm:: Intrinsic ,
103+ param_types : & [ & ' ll Type ] ,
104+ ) -> & ' ll Value {
105+ unsafe {
106+ llvm:: LLVMGetIntrinsicDeclaration (
107+ self . cx . llmod ( ) ,
108+ intrinsic. id ( ) ,
109+ param_types. as_ptr ( ) ,
110+ param_types. len ( ) . try_into ( ) . unwrap ( ) ,
111+ )
112+ }
113+ }
114+
115+ pub ( crate ) fn intrinsic_type (
116+ & mut self ,
117+ intrinsic : llvm:: Intrinsic ,
118+ param_types : & [ & ' ll Type ] ,
119+ ) -> & ' ll Type {
120+ unsafe {
121+ llvm:: LLVMIntrinsicGetType (
122+ self . cx . llcx ( ) ,
123+ intrinsic. id ( ) ,
124+ param_types. as_ptr ( ) ,
125+ param_types. len ( ) . try_into ( ) . unwrap ( ) ,
126+ )
127+ }
128+ }
129+
100130 pub ( crate ) fn bitcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
101131 unsafe { llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, UNNAMED ) }
102132 }
103133
134+ pub ( crate ) fn cast_vector_to_tile ( & mut self , val : & ' ll Value ) -> & ' ll Value {
135+ let vector_type = self . cx . val_ty ( val) ;
136+
137+ assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
138+
139+ let intrinsic =
140+ llvm:: Intrinsic :: try_from ( b"llvm.x86.cast.vector.to.tile" . as_ref ( ) ) . unwrap ( ) ;
141+ let fn_ty = self . intrinsic_type ( intrinsic, & [ vector_type] ) ;
142+ let f = self . declare_intrinsic ( intrinsic, & [ vector_type] ) ;
143+ unsafe {
144+ llvm:: LLVMBuildCallWithOperandBundles (
145+ self . llbuilder ,
146+ fn_ty,
147+ f,
148+ [ val] . as_ptr ( ) . cast ( ) ,
149+ 1 ,
150+ [ ] . as_ptr ( ) ,
151+ 0 ,
152+ c"" . as_ptr ( ) ,
153+ )
154+ }
155+ }
156+
157+ pub ( crate ) fn cast_tile_to_vector (
158+ & mut self ,
159+ val : & ' ll Value ,
160+ vector_type : & ' ll Type ,
161+ ) -> & ' ll Value {
162+ assert ! ( self . cx. val_ty( val) == self . cx. type_x86amx( ) ) ;
163+ assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
164+
165+ let intrinsic =
166+ llvm:: Intrinsic :: try_from ( b"llvm.x86.cast.tile.to.vector" . as_ref ( ) ) . unwrap ( ) ;
167+ let fn_ty = self . intrinsic_type ( intrinsic, & [ vector_type] ) ;
168+ let f = self . declare_intrinsic ( intrinsic, & [ vector_type] ) ;
169+ unsafe {
170+ llvm:: LLVMBuildCallWithOperandBundles (
171+ self . llbuilder ,
172+ fn_ty,
173+ f,
174+ [ val] . as_ptr ( ) . cast ( ) ,
175+ 1 ,
176+ [ ] . as_ptr ( ) ,
177+ 0 ,
178+ c"" . as_ptr ( ) ,
179+ )
180+ }
181+ }
182+
104183 pub ( crate ) fn ret_void ( & mut self ) {
105184 llvm:: LLVMBuildRetVoid ( self . llbuilder ) ;
106185 }
@@ -349,7 +428,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
349428 ) -> & ' ll Value {
350429 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
351430
352- let args = self . check_call ( "invoke" , llty, llfn, args) ;
431+ let args = self . cast_arguments ( "invoke" , llty, llfn, args) ;
353432 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
354433 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
355434 if let Some ( funclet_bundle) = funclet_bundle {
@@ -381,8 +460,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
381460 } ;
382461 if let Some ( fn_abi) = fn_abi {
383462 fn_abi. apply_attrs_callsite ( self , invoke) ;
463+ self . cast_return ( fn_abi, llfn, invoke)
464+ } else {
465+ invoke
384466 }
385- invoke
386467 }
387468
388469 fn unreachable ( & mut self ) {
@@ -1404,7 +1485,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14041485 ) -> & ' ll Value {
14051486 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
14061487
1407- let args = self . check_call ( "call" , llty, llfn, args) ;
1488+ let args = self . cast_arguments ( "call" , llty, llfn, args) ;
14081489 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
14091490 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
14101491 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1434,8 +1515,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14341515 } ;
14351516 if let Some ( fn_abi) = fn_abi {
14361517 fn_abi. apply_attrs_callsite ( self , call) ;
1518+ self . cast_return ( fn_abi, llfn, call)
1519+ } else {
1520+ call
14371521 }
1438- call
14391522 }
14401523
14411524 fn zext ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
@@ -1596,7 +1679,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
15961679 ret. expect ( "LLVM does not have support for catchret" )
15971680 }
15981681
1599- fn check_call < ' b > (
1682+ fn cast_arguments < ' b > (
16001683 & mut self ,
16011684 typ : & str ,
16021685 fn_ty : & ' ll Type ,
@@ -1627,7 +1710,11 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16271710 Expected {:?} for param {}, got {:?}; injecting bitcast",
16281711 llfn, expected_ty, i, actual_ty
16291712 ) ;
1630- self . bitcast ( actual_val, expected_ty)
1713+ if self . cx . type_kind ( expected_ty) == TypeKind :: X86_AMX {
1714+ self . cast_vector_to_tile ( actual_val)
1715+ } else {
1716+ self . bitcast ( actual_val, expected_ty)
1717+ }
16311718 } else {
16321719 actual_val
16331720 }
@@ -1708,6 +1795,31 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17081795 self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None , None )
17091796 }
17101797
1798+ fn cast_return (
1799+ & mut self ,
1800+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1801+ llfn : & ' ll Value ,
1802+ ret : & ' ll Value ,
1803+ ) -> & ' ll Value {
1804+ let expected_ty = fn_abi. llvm_return_type ( self . cx ) ;
1805+ let actual_ty = self . cx . val_ty ( ret) ;
1806+
1807+ if expected_ty != actual_ty {
1808+ debug ! (
1809+ "type mismatch in function call of {:?}. \
1810+ Expected {:?} for return value, got {:?}; injecting bitcast",
1811+ llfn, expected_ty, actual_ty
1812+ ) ;
1813+ if self . cx . type_kind ( actual_ty) == TypeKind :: X86_AMX {
1814+ self . cast_tile_to_vector ( ret, expected_ty)
1815+ } else {
1816+ self . bitcast ( ret, expected_ty)
1817+ }
1818+ } else {
1819+ ret
1820+ }
1821+ }
1822+
17111823 pub ( crate ) fn landing_pad (
17121824 & mut self ,
17131825 ty : & ' ll Type ,
@@ -1737,7 +1849,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17371849 ) -> & ' ll Value {
17381850 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
17391851
1740- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1852+ let args = self . cast_arguments ( "callbr" , llty, llfn, args) ;
17411853 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
17421854 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
17431855 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1770,8 +1882,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17701882 } ;
17711883 if let Some ( fn_abi) = fn_abi {
17721884 fn_abi. apply_attrs_callsite ( self , callbr) ;
1885+ self . cast_return ( fn_abi, llfn, callbr)
1886+ } else {
1887+ callbr
17731888 }
1774- callbr
17751889 }
17761890
17771891 // Emits CFI pointer type membership tests.
0 commit comments