@@ -67,7 +67,7 @@ impl<'a, 'll> SBuilder<'a, 'll> {
67
67
) -> & ' ll Value {
68
68
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
69
69
70
- let args = self . check_call ( "call" , llty, llfn, args) ;
70
+ let args = self . cast_arguments ( "call" , llty, llfn, args) ;
71
71
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
72
72
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
73
73
if let Some ( funclet_bundle) = funclet_bundle {
@@ -97,10 +97,89 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
97
97
GenericBuilder { llbuilder, cx : scx }
98
98
}
99
99
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
+
100
130
pub ( crate ) fn bitcast ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
101
131
unsafe { llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, UNNAMED ) }
102
132
}
103
133
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
+
104
183
pub ( crate ) fn ret_void ( & mut self ) {
105
184
llvm:: LLVMBuildRetVoid ( self . llbuilder ) ;
106
185
}
@@ -349,7 +428,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
349
428
) -> & ' ll Value {
350
429
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
351
430
352
- let args = self . check_call ( "invoke" , llty, llfn, args) ;
431
+ let args = self . cast_arguments ( "invoke" , llty, llfn, args) ;
353
432
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
354
433
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
355
434
if let Some ( funclet_bundle) = funclet_bundle {
@@ -381,8 +460,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
381
460
} ;
382
461
if let Some ( fn_abi) = fn_abi {
383
462
fn_abi. apply_attrs_callsite ( self , invoke) ;
463
+ self . cast_return ( fn_abi, llfn, invoke)
464
+ } else {
465
+ invoke
384
466
}
385
- invoke
386
467
}
387
468
388
469
fn unreachable ( & mut self ) {
@@ -1404,7 +1485,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1404
1485
) -> & ' ll Value {
1405
1486
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
1406
1487
1407
- let args = self . check_call ( "call" , llty, llfn, args) ;
1488
+ let args = self . cast_arguments ( "call" , llty, llfn, args) ;
1408
1489
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1409
1490
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1410
1491
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1434,8 +1515,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1434
1515
} ;
1435
1516
if let Some ( fn_abi) = fn_abi {
1436
1517
fn_abi. apply_attrs_callsite ( self , call) ;
1518
+ self . cast_return ( fn_abi, llfn, call)
1519
+ } else {
1520
+ call
1437
1521
}
1438
- call
1439
1522
}
1440
1523
1441
1524
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> {
1596
1679
ret. expect ( "LLVM does not have support for catchret" )
1597
1680
}
1598
1681
1599
- fn check_call < ' b > (
1682
+ fn cast_arguments < ' b > (
1600
1683
& mut self ,
1601
1684
typ : & str ,
1602
1685
fn_ty : & ' ll Type ,
@@ -1627,7 +1710,11 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1627
1710
Expected {:?} for param {}, got {:?}; injecting bitcast",
1628
1711
llfn, expected_ty, i, actual_ty
1629
1712
) ;
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
+ }
1631
1718
} else {
1632
1719
actual_val
1633
1720
}
@@ -1708,6 +1795,31 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1708
1795
self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None , None )
1709
1796
}
1710
1797
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
+
1711
1823
pub ( crate ) fn landing_pad (
1712
1824
& mut self ,
1713
1825
ty : & ' ll Type ,
@@ -1737,7 +1849,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1737
1849
) -> & ' ll Value {
1738
1850
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
1739
1851
1740
- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1852
+ let args = self . cast_arguments ( "callbr" , llty, llfn, args) ;
1741
1853
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1742
1854
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1743
1855
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1770,8 +1882,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1770
1882
} ;
1771
1883
if let Some ( fn_abi) = fn_abi {
1772
1884
fn_abi. apply_attrs_callsite ( self , callbr) ;
1885
+ self . cast_return ( fn_abi, llfn, callbr)
1886
+ } else {
1887
+ callbr
1773
1888
}
1774
- callbr
1775
1889
}
1776
1890
1777
1891
// Emits CFI pointer type membership tests.
0 commit comments