@@ -255,31 +255,39 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
255255 . bit_reverse ( args[ 0 ] . immediate ( ) . ty , None , args[ 0 ] . immediate ( ) . def ( self ) )
256256 . unwrap ( )
257257 . with_type ( args[ 0 ] . immediate ( ) . ty ) ,
258-
259258 sym:: bswap => {
260259 // https://github.com/KhronosGroup/SPIRV-LLVM/pull/221/files
261260 // TODO: Definitely add tests to make sure this impl is right.
262261 let arg = args[ 0 ] . immediate ( ) ;
263- match int_type_width_signed ( arg_tys[ 0 ] , self )
264- . expect ( "bswap must have integer argument" )
265- . 0
266- {
267- 8 => arg,
262+ let ( width, is_signed) = int_type_width_signed ( arg_tys[ 0 ] , self )
263+ . expect ( "bswap must have an integer argument" ) ;
264+
265+ // Cast to unsigned type for byte-swapping
266+ let unsigned_ty: u32 =
267+ SpirvType :: Integer ( width. try_into ( ) . unwrap ( ) , false ) . def ( self . span ( ) , self ) ;
268+ let unsigned_arg = if is_signed {
269+ self . bitcast ( arg, unsigned_ty)
270+ } else {
271+ arg
272+ } ;
273+
274+ let swapped = match width {
275+ 8 => unsigned_arg,
268276 16 => {
269277 let offset8 = self . constant_u16 ( self . span ( ) , 8 ) ;
270- let tmp1 = self . shl ( arg , offset8) ;
271- let tmp2 = self . lshr ( arg , offset8) ;
278+ let tmp1 = self . shl ( unsigned_arg , offset8) ;
279+ let tmp2 = self . lshr ( unsigned_arg , offset8) ;
272280 self . or ( tmp1, tmp2)
273281 }
274282 32 => {
275283 let offset8 = self . constant_u32 ( self . span ( ) , 8 ) ;
276284 let offset24 = self . constant_u32 ( self . span ( ) , 24 ) ;
277285 let mask16 = self . constant_u32 ( self . span ( ) , 0xFF00 ) ;
278286 let mask24 = self . constant_u32 ( self . span ( ) , 0xFF0000 ) ;
279- let tmp4 = self . shl ( arg , offset24) ;
280- let tmp3 = self . shl ( arg , offset8) ;
281- let tmp2 = self . lshr ( arg , offset8) ;
282- let tmp1 = self . lshr ( arg , offset24) ;
287+ let tmp4 = self . shl ( unsigned_arg , offset24) ;
288+ let tmp3 = self . shl ( unsigned_arg , offset8) ;
289+ let tmp2 = self . lshr ( unsigned_arg , offset8) ;
290+ let tmp1 = self . lshr ( unsigned_arg , offset24) ;
283291 let tmp3 = self . and ( tmp3, mask24) ;
284292 let tmp2 = self . and ( tmp2, mask16) ;
285293 let res1 = self . or ( tmp1, tmp2) ;
@@ -297,14 +305,14 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
297305 let mask40 = self . constant_u64 ( self . span ( ) , 0xff00000000 ) ;
298306 let mask48 = self . constant_u64 ( self . span ( ) , 0xff0000000000 ) ;
299307 let mask56 = self . constant_u64 ( self . span ( ) , 0xff000000000000 ) ;
300- let tmp8 = self . shl ( arg , offset56) ;
301- let tmp7 = self . shl ( arg , offset40) ;
302- let tmp6 = self . shl ( arg , offset24) ;
303- let tmp5 = self . shl ( arg , offset8) ;
304- let tmp4 = self . lshr ( arg , offset8) ;
305- let tmp3 = self . lshr ( arg , offset24) ;
306- let tmp2 = self . lshr ( arg , offset40) ;
307- let tmp1 = self . lshr ( arg , offset56) ;
308+ let tmp8 = self . shl ( unsigned_arg , offset56) ;
309+ let tmp7 = self . shl ( unsigned_arg , offset40) ;
310+ let tmp6 = self . shl ( unsigned_arg , offset24) ;
311+ let tmp5 = self . shl ( unsigned_arg , offset8) ;
312+ let tmp4 = self . lshr ( unsigned_arg , offset8) ;
313+ let tmp3 = self . lshr ( unsigned_arg , offset24) ;
314+ let tmp2 = self . lshr ( unsigned_arg , offset40) ;
315+ let tmp1 = self . lshr ( unsigned_arg , offset56) ;
308316 let tmp7 = self . and ( tmp7, mask56) ;
309317 let tmp6 = self . and ( tmp6, mask48) ;
310318 let tmp5 = self . and ( tmp5, mask40) ;
@@ -327,6 +335,13 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
327335 ) ;
328336 undef
329337 }
338+ } ;
339+
340+ // Cast back to the original signed type if necessary
341+ if is_signed {
342+ self . bitcast ( swapped, arg. ty )
343+ } else {
344+ swapped
330345 }
331346 }
332347
0 commit comments