xref: /aosp_15_r20/external/swiftshader/src/Reactor/Pragma.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 = true;
34 	bool initializeLocalVariables = false;
35 	int optimizationLevel = 2;  // Default
36 };
37 
38 // The initialization of static thread-local data is not observed by MemorySanitizer
39 // when inside a shared library, leading to false-positive use-of-uninitialized-data
40 // errors: https://github.com/google/sanitizers/issues/1409
41 // We work around this by assigning an initial value to it ourselves on first use.
42 // Note that since the flag to check whether this initialization has already been
43 // done is itself a static thread-local, we must suppress the MemorySanitizer check
44 // with a function attribute.
getPragmaState()45 CLANG_NO_SANITIZE_MEMORY PragmaState &getPragmaState()
46 {
47 	static thread_local bool initialized = false;
48 	static thread_local PragmaState state;
49 
50 	if(!initialized)
51 	{
52 		state = {};
53 
54 		initialized = true;
55 	}
56 
57 	return state;
58 }
59 
60 }  // namespace
61 
62 namespace rr {
63 
Pragma(BooleanPragmaOption option,bool enable)64 void Pragma(BooleanPragmaOption option, bool enable)
65 {
66 	PragmaState &state = ::getPragmaState();
67 
68 	switch(option)
69 	{
70 	case MemorySanitizerInstrumentation:
71 		state.memorySanitizerInstrumentation = enable;
72 		break;
73 	case InitializeLocalVariables:
74 		state.initializeLocalVariables = enable;
75 		break;
76 	default:
77 		UNSUPPORTED("Unknown Boolean pragma option %d", int(option));
78 	}
79 }
80 
Pragma(IntegerPragmaOption option,int value)81 void Pragma(IntegerPragmaOption option, int value)
82 {
83 	PragmaState &state = ::getPragmaState();
84 
85 	switch(option)
86 	{
87 	case OptimizationLevel:
88 		state.optimizationLevel = value;
89 		break;
90 	default:
91 		UNSUPPORTED("Unknown integer pragma option %d", int(option));
92 	}
93 }
94 
getPragmaState(BooleanPragmaOption option)95 bool getPragmaState(BooleanPragmaOption option)
96 {
97 	PragmaState &state = ::getPragmaState();
98 
99 	switch(option)
100 	{
101 	case MemorySanitizerInstrumentation:
102 		return state.memorySanitizerInstrumentation;
103 	case InitializeLocalVariables:
104 		return state.initializeLocalVariables;
105 	default:
106 		UNSUPPORTED("Unknown Boolean pragma option %d", int(option));
107 		return false;
108 	}
109 }
110 
getPragmaState(IntegerPragmaOption option)111 int getPragmaState(IntegerPragmaOption option)
112 {
113 	PragmaState &state = ::getPragmaState();
114 
115 	switch(option)
116 	{
117 	case OptimizationLevel:
118 		return state.optimizationLevel;
119 	default:
120 		UNSUPPORTED("Unknown integer pragma option %d", int(option));
121 		return 0;
122 	}
123 }
124 
ScopedPragma(BooleanPragmaOption option,bool enable)125 ScopedPragma::ScopedPragma(BooleanPragmaOption option, bool enable)
126 {
127 	oldState = BooleanPragma{ option, getPragmaState(option) };
128 	Pragma(option, enable);
129 }
130 
ScopedPragma(IntegerPragmaOption option,int value)131 ScopedPragma::ScopedPragma(IntegerPragmaOption option, int value)
132 {
133 	oldState = IntegerPragma{ option, getPragmaState(option) };
134 	Pragma(option, value);
135 }
136 
~ScopedPragma()137 ScopedPragma::~ScopedPragma()
138 {
139 	if(std::holds_alternative<BooleanPragma>(oldState))
140 	{
141 		auto &restore = std::get<BooleanPragma>(oldState);
142 		Pragma(restore.option, restore.enable);
143 	}
144 	else
145 	{
146 		auto &restore = std::get<IntegerPragma>(oldState);
147 		Pragma(restore.option, restore.value);
148 	}
149 }
150 
151 }  // namespace rr