@@ -678,49 +678,54 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
678678 // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
679679 ( _, name) if name. starts_with ( "atomic_" ) => {
680680 let split: Vec < & str > = name. split ( '_' ) . collect ( ) ;
681- assert ! ( split. len( ) >= 2 , "Atomic intrinsic not correct format" ) ;
682681
683- let order = if split. len ( ) == 2 {
684- llvm:: SequentiallyConsistent
685- } else {
686- match split[ 2 ] {
687- "unordered" => llvm:: Unordered ,
688- "relaxed" => llvm:: Monotonic ,
689- "acq" => llvm:: Acquire ,
690- "rel" => llvm:: Release ,
691- "acqrel" => llvm:: AcquireRelease ,
682+ let ( order, failorder) = match split. len ( ) {
683+ 2 => ( llvm:: SequentiallyConsistent , llvm:: SequentiallyConsistent ) ,
684+ 3 => match split[ 2 ] {
685+ "unordered" => ( llvm:: Unordered , llvm:: Unordered ) ,
686+ "relaxed" => ( llvm:: Monotonic , llvm:: Monotonic ) ,
687+ "acq" => ( llvm:: Acquire , llvm:: Acquire ) ,
688+ "rel" => ( llvm:: Release , llvm:: Monotonic ) ,
689+ "acqrel" => ( llvm:: AcquireRelease , llvm:: Acquire ) ,
690+ "failrelaxed" if split[ 1 ] == "cxchg" || split[ 1 ] == "cxchgweak" =>
691+ ( llvm:: SequentiallyConsistent , llvm:: Monotonic ) ,
692+ "failacq" if split[ 1 ] == "cxchg" || split[ 1 ] == "cxchgweak" =>
693+ ( llvm:: SequentiallyConsistent , llvm:: Acquire ) ,
692694 _ => ccx. sess ( ) . fatal ( "unknown ordering in atomic intrinsic" )
693- }
695+ } ,
696+ 4 => match ( split[ 2 ] , split[ 3 ] ) {
697+ ( "acq" , "failrelaxed" ) if split[ 1 ] == "cxchg" || split[ 1 ] == "cxchgweak" =>
698+ ( llvm:: Acquire , llvm:: Monotonic ) ,
699+ ( "acqrel" , "failrelaxed" ) if split[ 1 ] == "cxchg" || split[ 1 ] == "cxchgweak" =>
700+ ( llvm:: AcquireRelease , llvm:: Monotonic ) ,
701+ _ => ccx. sess ( ) . fatal ( "unknown ordering in atomic intrinsic" )
702+ } ,
703+ _ => ccx. sess ( ) . fatal ( "Atomic intrinsic not in correct format" ) ,
694704 } ;
695705
696706 match split[ 1 ] {
697707 "cxchg" => {
698- // See include/llvm/IR/Instructions.h for their implementation
699- // of this, I assume that it's good enough for us to use for
700- // now.
701- let strongest_failure_ordering = match order {
702- llvm:: NotAtomic | llvm:: Unordered =>
703- ccx. sess ( ) . fatal ( "cmpxchg must be atomic" ) ,
704-
705- llvm:: Monotonic | llvm:: Release =>
706- llvm:: Monotonic ,
707-
708- llvm:: Acquire | llvm:: AcquireRelease =>
709- llvm:: Acquire ,
710-
711- llvm:: SequentiallyConsistent =>
712- llvm:: SequentiallyConsistent
713- } ;
714-
715708 let tp_ty = * substs. types . get ( FnSpace , 0 ) ;
716709 let ptr = to_arg_ty_ptr ( bcx, llargs[ 0 ] , tp_ty) ;
717710 let cmp = from_arg_ty ( bcx, llargs[ 1 ] , tp_ty) ;
718711 let src = from_arg_ty ( bcx, llargs[ 2 ] , tp_ty) ;
719- let res = AtomicCmpXchg ( bcx, ptr, cmp, src, order,
720- strongest_failure_ordering) ;
712+ let res = AtomicCmpXchg ( bcx, ptr, cmp, src, order, failorder, llvm:: False ) ;
721713 ExtractValue ( bcx, res, 0 )
722714 }
723715
716+ "cxchgweak" => {
717+ let tp_ty = * substs. types . get ( FnSpace , 0 ) ;
718+ let ptr = to_arg_ty_ptr ( bcx, llargs[ 0 ] , tp_ty) ;
719+ let cmp = from_arg_ty ( bcx, llargs[ 1 ] , tp_ty) ;
720+ let src = from_arg_ty ( bcx, llargs[ 2 ] , tp_ty) ;
721+ let val = AtomicCmpXchg ( bcx, ptr, cmp, src, order, failorder, llvm:: True ) ;
722+ let result = ExtractValue ( bcx, val, 0 ) ;
723+ let success = ZExt ( bcx, ExtractValue ( bcx, val, 1 ) , Type :: bool ( bcx. ccx ( ) ) ) ;
724+ Store ( bcx, result, StructGEP ( bcx, llresult, 0 ) ) ;
725+ Store ( bcx, success, StructGEP ( bcx, llresult, 1 ) ) ;
726+ C_nil ( ccx)
727+ }
728+
724729 "load" => {
725730 let tp_ty = * substs. types . get ( FnSpace , 0 ) ;
726731 let ptr = to_arg_ty_ptr ( bcx, llargs[ 0 ] , tp_ty) ;
0 commit comments