blob: 1175352d3b14620d82ba2dfbca7f4e31a4215e07 [file] [log] [blame]
Nicolas Capensc9991d42021-06-16 00:46:28 -04001// 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
Nicolas Capens314508f2021-07-01 01:23:28 -040020// 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
Nicolas Capensc9991d42021-06-16 00:46:28 -040028
Nicolas Capens314508f2021-07-01 01:23:28 -040029namespace {
30
31struct PragmaState
32{
Nicolas Capens80de2012022-05-13 13:43:21 -040033 bool memorySanitizerInstrumentation = true;
Nicolas Capensd0703092022-05-26 12:58:20 -040034 bool initializeLocalVariables = false;
Nicolas Capens79d4c6c2022-04-22 17:20:26 -040035 int optimizationLevel = 2; // Default
Nicolas Capens314508f2021-07-01 01:23:28 -040036};
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.
45CLANG_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
62namespace rr {
Nicolas Capensc9991d42021-06-16 00:46:28 -040063
Nicolas Capens25c75982022-04-22 14:40:56 -040064void Pragma(BooleanPragmaOption option, bool enable)
Nicolas Capensc9991d42021-06-16 00:46:28 -040065{
Nicolas Capens314508f2021-07-01 01:23:28 -040066 PragmaState &state = ::getPragmaState();
67
Nicolas Capensc9991d42021-06-16 00:46:28 -040068 switch(option)
69 {
70 case MemorySanitizerInstrumentation:
Nicolas Capens314508f2021-07-01 01:23:28 -040071 state.memorySanitizerInstrumentation = enable;
Nicolas Capensc9991d42021-06-16 00:46:28 -040072 break;
Nicolas Capensd0703092022-05-26 12:58:20 -040073 case InitializeLocalVariables:
74 state.initializeLocalVariables = enable;
75 break;
Nicolas Capensc9991d42021-06-16 00:46:28 -040076 default:
Nicolas Capens25c75982022-04-22 14:40:56 -040077 UNSUPPORTED("Unknown Boolean pragma option %d", int(option));
Nicolas Capensc9991d42021-06-16 00:46:28 -040078 }
79}
80
Nicolas Capens79d4c6c2022-04-22 17:20:26 -040081void 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
Nicolas Capens25c75982022-04-22 14:40:56 -040095bool getPragmaState(BooleanPragmaOption option)
Nicolas Capensc9991d42021-06-16 00:46:28 -040096{
Nicolas Capens314508f2021-07-01 01:23:28 -040097 PragmaState &state = ::getPragmaState();
98
Nicolas Capensc9991d42021-06-16 00:46:28 -040099 switch(option)
100 {
101 case MemorySanitizerInstrumentation:
Nicolas Capens314508f2021-07-01 01:23:28 -0400102 return state.memorySanitizerInstrumentation;
Nicolas Capensd0703092022-05-26 12:58:20 -0400103 case InitializeLocalVariables:
104 return state.initializeLocalVariables;
Nicolas Capensc9991d42021-06-16 00:46:28 -0400105 default:
Nicolas Capens25c75982022-04-22 14:40:56 -0400106 UNSUPPORTED("Unknown Boolean pragma option %d", int(option));
Nicolas Capensc9991d42021-06-16 00:46:28 -0400107 return false;
108 }
109}
110
Nicolas Capens79d4c6c2022-04-22 17:20:26 -0400111int 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
Nicolas Capens25c75982022-04-22 14:40:56 -0400125ScopedPragma::ScopedPragma(BooleanPragmaOption option, bool enable)
126{
127 oldState = BooleanPragma{ option, getPragmaState(option) };
128 Pragma(option, enable);
129}
130
Nicolas Capens79d4c6c2022-04-22 17:20:26 -0400131ScopedPragma::ScopedPragma(IntegerPragmaOption option, int value)
132{
133 oldState = IntegerPragma{ option, getPragmaState(option) };
134 Pragma(option, value);
135}
136
Nicolas Capens25c75982022-04-22 14:40:56 -0400137ScopedPragma::~ScopedPragma()
138{
Nicolas Capens79d4c6c2022-04-22 17:20:26 -0400139 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 }
Nicolas Capens25c75982022-04-22 14:40:56 -0400149}
150
Nicolas Capensc9991d42021-06-16 00:46:28 -0400151} // namespace rr