name = "msanwrite"
}
f = mkcall(name, nil, init, uintptraddr(n), nodintconst(w))
- } else if flag_race && (t.IsStruct() || t.IsArray()) {
+ } else if flag_race && t.NumComponents() > 1 {
+ // for composite objects we have to write every address
+ // because a write might happen to any subobject.
+ // composites with only one element don't have subobjects, though.
name := "racereadrange"
if wr != 0 {
name = "racewriterange"
}
f = mkcall(name, nil, init, uintptraddr(n), nodintconst(w))
} else if flag_race {
+ // for non-composite objects we can write just the start
+ // address, as any write must write the first byte.
name := "raceread"
if wr != 0 {
name = "racewrite"
at.Bound = n
}
+func (t *Type) NumComponents() int64 {
+ switch t.Etype {
+ case TSTRUCT:
+ if t.IsFuncArgStruct() {
+ Fatalf("NumComponents func arg struct")
+ }
+ var n int64
+ for _, f := range t.FieldSlice() {
+ n += f.Type.NumComponents()
+ }
+ return n
+ case TARRAY:
+ return t.NumElem() * t.Elem().NumComponents()
+ }
+ return 1
+}
+
// ChanDir returns the direction of a channel type t.
// The direction will be one of Crecv, Csend, or Cboth.
func (t *Type) ChanDir() ChanDir {