@@ -232,7 +232,6 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
232232 // Get the return type.
233233 let sig = llvm:: LLVMGetElementType ( self . val_ty ( self . llfn ( ) ) ) ;
234234 let return_ty = llvm:: LLVMGetReturnType ( sig) ;
235- ;
236235 // Check if new_ty & return_ty are different pointers.
237236 // FIXME: get rid of this nonsense once we are past LLVM 7 and don't have
238237 // to suffer from typed pointers.
@@ -1195,13 +1194,15 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11951194 ) ;
11961195 }
11971196 } ;
1198- let tuple = self . type_struct ( & [ self . val_ty ( src) , self . type_i1 ( ) ] , false ) ;
1197+ let tuple = self . type_struct ( & [ self . val_ty ( src) , self . type_i1 ( ) ] , false ) ;
11991198 let res = self . atomic_op (
12001199 dst,
12011200 tuple,
1202- |builder, dst, ty| {
1203- builder. abort ( ) ;
1204- return builder. const_undef ( ty) ;
1201+ |builder, dst, ty| {
1202+ let address_space =
1203+ unsafe { llvm:: LLVMGetPointerAddressSpace ( builder. val_ty ( dst) ) } ;
1204+ let dst_ty = unsafe { llvm:: LLVMPointerType ( builder. val_ty ( cmp) , address_space) } ;
1205+ let dst = builder. pointercast ( dst, dst_ty) ;
12051206 // We are in a supported address space - just use ordinary atomics
12061207 unsafe {
12071208 llvm:: LLVMRustBuildAtomicCmpXchg (
@@ -1215,7 +1216,13 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12151216 )
12161217 }
12171218 } ,
1218- |builder, dst, ty| {
1219+ |builder, dst, ty| {
1220+ let dst = builder. pointercast ( dst, unsafe {
1221+ llvm:: LLVMPointerType (
1222+ builder. val_ty ( cmp) ,
1223+ llvm:: LLVMGetPointerAddressSpace ( builder. val_ty ( dst) ) ,
1224+ )
1225+ } ) ;
12191226 // Local space is only accessible to the current thread.
12201227 // So, there are no synchronization issues, and we can emulate it using a simple load / compare / store.
12211228 let load: & ' ll Value =
@@ -1253,12 +1260,12 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12531260 self . atomic_op (
12541261 dst,
12551262 self . val_ty ( src) ,
1256- |builder, dst, ty| {
1263+ |builder, dst, ty| {
12571264 // We are in a supported address space - just use ordinary atomics
1258- let address_space = unsafe { llvm:: LLVMGetPointerAddressSpace ( builder. val_ty ( dst) ) } ;
1265+ let address_space =
1266+ unsafe { llvm:: LLVMGetPointerAddressSpace ( builder. val_ty ( dst) ) } ;
12591267 let dst_ty = unsafe { llvm:: LLVMPointerType ( ty, address_space) } ;
1260- let dst = builder. pointercast ( dst, dst_ty) ;
1261- let src = if matches ! ( op, AtomicRmwBinOp :: AtomicXchg ) { builder. pointercast ( src, dst_ty) } else { src} ;
1268+ let dst = builder. pointercast ( dst, dst_ty) ;
12621269 unsafe {
12631270 llvm:: LLVMBuildAtomicRMW (
12641271 builder. llbuilder ,
@@ -1270,9 +1277,13 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12701277 )
12711278 }
12721279 } ,
1273- |builder, dst, ty| {
1280+ |builder, dst, ty| {
12741281 // Local space is only accessible to the current thread.
12751282 // So, there are no synchronization issues, and we can emulate it using a simple load / compare / store.
1283+ let dst = builder. pointercast ( dst, unsafe {
1284+ llvm:: LLVMPointerType ( ty, llvm:: LLVMGetPointerAddressSpace ( builder. val_ty ( dst) ) )
1285+ } ) ;
1286+
12761287 let load: & ' ll Value =
12771288 unsafe { llvm:: LLVMBuildLoad ( builder. llbuilder , dst, UNNAMED ) } ;
12781289 let next_val = match op {
@@ -1352,13 +1363,13 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
13521363 let mut call = unsafe {
13531364 let llfn = if self . cx . type_kind ( llty) == TypeKind :: Pointer {
13541365 self . pointercast ( llfn, llty)
1355- } else if self . cx . type_kind ( self . val_ty ( llfn) ) == TypeKind :: Pointer {
1366+ } else if self . cx . type_kind ( self . val_ty ( llfn) ) == TypeKind :: Pointer {
13561367 let target_fnptr = llvm:: LLVMPointerType ( llty, 0 ) ;
13571368 self . pointercast ( llfn, target_fnptr)
13581369 } else {
13591370 llfn
13601371 } ;
1361-
1372+
13621373 llvm:: LLVMRustBuildCall (
13631374 self . llbuilder ,
13641375 llfn,
@@ -1794,16 +1805,10 @@ impl<'ll, 'tcx, 'a> Builder<'a, 'll, 'tcx> {
17941805 fn atomic_op (
17951806 & mut self ,
17961807 dst : & ' ll Value ,
1797- ty : & ' ll Type ,
1798- atomic_supported : impl FnOnce ( & mut Builder < ' a , ' ll , ' tcx > , & ' ll Value , & ' ll Type ) -> & ' ll Value ,
1799- emulate_local : impl FnOnce ( & mut Builder < ' a , ' ll , ' tcx > , & ' ll Value , & ' ll Type ) -> & ' ll Value ,
1808+ ty : & ' ll Type ,
1809+ atomic_supported : impl FnOnce ( & mut Builder < ' a , ' ll , ' tcx > , & ' ll Value , & ' ll Type ) -> & ' ll Value ,
1810+ emulate_local : impl FnOnce ( & mut Builder < ' a , ' ll , ' tcx > , & ' ll Value , & ' ll Type ) -> & ' ll Value ,
18001811 ) -> & ' ll Value {
1801-
1802- let emulate_local = |builder : & mut Self , _, _|{
1803- // ATOMICS don't work with untyped pointers *YET*.
1804- builder. abort ( ) ;
1805- builder. const_undef ( ty)
1806- } ;
18071812 // (FractalFir) Atomics in CUDA have some limitations, and we have to work around them.
18081813 // For example, they are restricted in what address space they operate on.
18091814 // CUDA has 4 address spaces(and a generic one, which is an union of all of those).
@@ -1873,7 +1878,7 @@ impl<'ll, 'tcx, 'a> Builder<'a, 'll, 'tcx> {
18731878 self . cond_br ( isspacep_local, local_bb, atomic_ub_bb) ;
18741879 // The pointer is in the thread(local) space.
18751880 self . switch_to_block ( local_bb) ;
1876- let local_res = emulate_local ( self , dst, ty) ;
1881+ let local_res = emulate_local ( self , dst, ty) ;
18771882 self . br ( merge_bb) ;
18781883 // The pointer is neither in the supported address space, nor the local space.
18791884 // This is very likely UB. So, we trap here.
0 commit comments