• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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