package main import ( "fmt" "os" "text/template" ) func main() { fmt.Print(header) for size := uint32(0); size < 5; size++ { for _, order := range []string{"unordered", "monotonic", "acquire", "seq_cst"} { output(loadTempl, size, order) } for _, order := range []string{"unordered", "monotonic", "release", "seq_cst"} { output(storeTempl, size, order) } } } func output(templ *template.Template, size uint32, order string) { data := map[string]string{ "Size": fmt.Sprint(8 * (1 << size)), "ByteSize": fmt.Sprint(1 << size), "Order": order, "TsanOrder": tsanOrders[order], } templ.Execute(os.Stdout, data) } var tsanOrders = map[string]string{ "unordered": "1", "monotonic": "1", "consume": "2", "acquire": "4", "release": "8", "acq_rel": "16", "seq_cst": "32", } var loadTempl = template.Must(template.New("foo").Parse(` define i{{.Size}} @atomic{{.Size}}_load_{{.Order}}(i{{.Size}}* %a) nounwind uwtable { entry: %0 = load atomic i{{.Size}}* %a {{.Order}}, align {{.ByteSize}} ret i{{.Size}} %0 } ; CHECK: atomic{{.Size}}_load_{{.Order}} ; CHECK: call i{{.Size}} @__tsan_atomic{{.Size}}_load(i{{.Size}}* %a, i32 {{.TsanOrder}}) `)) var storeTempl = template.Must(template.New("foo").Parse(` define void @atomic{{.Size}}_store_{{.Order}}(i{{.Size}}* %a) nounwind uwtable { entry: store atomic i{{.Size}} 0, i{{.Size}}* %a {{.Order}}, align {{.ByteSize}} ret void } ; CHECK: atomic{{.Size}}_store_{{.Order}} ; CHECK: call void @__tsan_atomic{{.Size}}_store(i{{.Size}}* %a, i{{.Size}} 0, i32 {{.TsanOrder}}) `)) var header = `; RUN: opt < %s -tsan -S | FileCheck %s ; Check that atomic memory operations are converted to calls into ThreadSanitizer runtime. target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" `