@@ -255,31 +255,39 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
255
255
. bit_reverse ( args[ 0 ] . immediate ( ) . ty , None , args[ 0 ] . immediate ( ) . def ( self ) )
256
256
. unwrap ( )
257
257
. with_type ( args[ 0 ] . immediate ( ) . ty ) ,
258
-
259
258
sym:: bswap => {
260
259
// https://github.com/KhronosGroup/SPIRV-LLVM/pull/221/files
261
260
// TODO: Definitely add tests to make sure this impl is right.
262
261
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,
268
276
16 => {
269
277
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) ;
272
280
self . or ( tmp1, tmp2)
273
281
}
274
282
32 => {
275
283
let offset8 = self . constant_u32 ( self . span ( ) , 8 ) ;
276
284
let offset24 = self . constant_u32 ( self . span ( ) , 24 ) ;
277
285
let mask16 = self . constant_u32 ( self . span ( ) , 0xFF00 ) ;
278
286
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) ;
283
291
let tmp3 = self . and ( tmp3, mask24) ;
284
292
let tmp2 = self . and ( tmp2, mask16) ;
285
293
let res1 = self . or ( tmp1, tmp2) ;
@@ -297,14 +305,14 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
297
305
let mask40 = self . constant_u64 ( self . span ( ) , 0xff00000000 ) ;
298
306
let mask48 = self . constant_u64 ( self . span ( ) , 0xff0000000000 ) ;
299
307
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) ;
308
316
let tmp7 = self . and ( tmp7, mask56) ;
309
317
let tmp6 = self . and ( tmp6, mask48) ;
310
318
let tmp5 = self . and ( tmp5, mask40) ;
@@ -327,6 +335,13 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
327
335
) ;
328
336
undef
329
337
}
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
330
345
}
331
346
}
332
347
0 commit comments