1 // Copyright 2021 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "Pragma.hpp"
16 #include "PragmaInternals.hpp"
17
18 #include "Debug.hpp"
19
20 // The CLANG_NO_SANITIZE_MEMORY macro suppresses MemorySanitizer checks for
21 // use-of-uninitialized-data. It is used to decorate functions with known
22 // false positives.
23 #ifdef __clang__
24 # define CLANG_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
25 #else
26 # define CLANG_NO_SANITIZE_MEMORY
27 #endif
28
29 namespace {
30
31 struct PragmaState
32 {
33 bool memorySanitizerInstrumentation;
34 };
35
36 // The initialization of static thread-local data is not observed by MemorySanitizer
37 // when inside a shared library, leading to false-positive use-of-uninitialized-data
38 // errors: https://github.com/google/sanitizers/issues/1409
39 // We work around this by assigning an initial value to it ourselves on first use.
40 // Note that since the flag to check whether this initialization has already been
41 // done is itself a static thread-local, we must suppress the MemorySanitizer check
42 // with a function attribute.
getPragmaState()43 CLANG_NO_SANITIZE_MEMORY PragmaState &getPragmaState()
44 {
45 static thread_local bool initialized = false;
46 static thread_local PragmaState state;
47
48 if(!initialized)
49 {
50 state = {};
51
52 initialized = true;
53 }
54
55 return state;
56 }
57
58 } // namespace
59
60 namespace rr {
61
Pragma(PragmaBooleanOption option,bool enable)62 void Pragma(PragmaBooleanOption option, bool enable)
63 {
64 PragmaState &state = ::getPragmaState();
65
66 switch(option)
67 {
68 case MemorySanitizerInstrumentation:
69 state.memorySanitizerInstrumentation = enable;
70 break;
71 default:
72 UNSUPPORTED("Unknown pragma %d", int(option));
73 }
74 }
75
getPragmaState(PragmaBooleanOption option)76 bool getPragmaState(PragmaBooleanOption option)
77 {
78 PragmaState &state = ::getPragmaState();
79
80 switch(option)
81 {
82 case MemorySanitizerInstrumentation:
83 return state.memorySanitizerInstrumentation;
84 default:
85 UNSUPPORTED("Unknown pragma %d", int(option));
86 return false;
87 }
88 }
89
90 } // namespace rr