11package compiler
22
33import (
4+ "fmt"
45 "strings"
56
67 "golang.org/x/tools/go/ssa"
@@ -16,6 +17,20 @@ func (b *builder) createAtomicOp(call *ssa.CallCommon) (llvm.Value, bool) {
1617 case "AddInt32" , "AddInt64" , "AddUint32" , "AddUint64" , "AddUintptr" :
1718 ptr := b .getValue (call .Args [0 ])
1819 val := b .getValue (call .Args [1 ])
20+ if strings .HasPrefix (b .Triple , "avr" ) {
21+ // AtomicRMW does not work on AVR as intended:
22+ // - There are some register allocation issues (fixed by https://reviews.llvm.org/D97127 which is not yet in a usable LLVM release)
23+ // - The result is the new value instead of the old value
24+ vType := val .Type ()
25+ name := fmt .Sprintf ("__sync_fetch_and_add_%d" , vType .IntTypeWidth ()/ 8 )
26+ fn := b .mod .NamedFunction (name )
27+ if fn .IsNil () {
28+ fn = llvm .AddFunction (b .mod , name , llvm .FunctionType (vType , []llvm.Type {ptr .Type (), vType }, false ))
29+ }
30+ oldVal := b .createCall (fn , []llvm.Value {ptr , val }, "" )
31+ // Return the new value, not the original value returned.
32+ return b .CreateAdd (oldVal , val , "" ), true
33+ }
1934 oldVal := b .CreateAtomicRMW (llvm .AtomicRMWBinOpAdd , ptr , val , llvm .AtomicOrderingSequentiallyConsistent , true )
2035 // Return the new value, not the original value returned by atomicrmw.
2136 return b .CreateAdd (oldVal , val , "" ), true
@@ -73,6 +88,23 @@ func (b *builder) createAtomicOp(call *ssa.CallCommon) (llvm.Value, bool) {
7388 case "StoreInt32" , "StoreInt64" , "StoreUint32" , "StoreUint64" , "StoreUintptr" , "StorePointer" :
7489 ptr := b .getValue (call .Args [0 ])
7590 val := b .getValue (call .Args [1 ])
91+ if strings .HasPrefix (b .Triple , "avr" ) {
92+ // SelectionDAGBuilder is currently missing the "are unaligned atomics allowed" check for stores.
93+ vType := val .Type ()
94+ isPointer := vType .TypeKind () == llvm .PointerTypeKind
95+ if isPointer {
96+ // libcalls only supports integers, so cast to an integer.
97+ vType = b .uintptrType
98+ val = b .CreatePtrToInt (val , vType , "" )
99+ ptr = b .CreateBitCast (ptr , llvm .PointerType (vType , 0 ), "" )
100+ }
101+ name := fmt .Sprintf ("__atomic_store_%d" , vType .IntTypeWidth ()/ 8 )
102+ fn := b .mod .NamedFunction (name )
103+ if fn .IsNil () {
104+ fn = llvm .AddFunction (b .mod , name , llvm .FunctionType (vType , []llvm.Type {ptr .Type (), vType , b .uintptrType }, false ))
105+ }
106+ return b .createCall (fn , []llvm.Value {ptr , val , llvm .ConstInt (b .uintptrType , 5 , false )}, "" ), true
107+ }
76108 store := b .CreateStore (val , ptr )
77109 store .SetOrdering (llvm .AtomicOrderingSequentiallyConsistent )
78110 store .SetAlignment (b .targetData .PrefTypeAlignment (val .Type ())) // required
0 commit comments