blob: 38e22add3962652d9491c18f116bda83e48dcd2f [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 Capens79d4c6c2022-04-22 17:20:26 -040034 int optimizationLevel = 2; // Default
Nicolas Capens314508f2021-07-01 01:23:28 -040035};
36
37// The initialization of static thread-local data is not observed by MemorySanitizer
38// when inside a shared library, leading to false-positive use-of-uninitialized-data
39// errors: https://github.com/google/sanitizers/issues/1409
40// We work around this by assigning an initial value to it ourselves on first use.
41// Note that since the flag to check whether this initialization has already been
42// done is itself a static thread-local, we must suppress the MemorySanitizer check
43// with a function attribute.
44CLANG_NO_SANITIZE_MEMORY PragmaState &getPragmaState()
45{
46 static thread_local bool initialized = false;
47 static thread_local PragmaState state;
48
49 if(!initialized)
50 {
51 state = {};
52
53 initialized = true;
54 }
55
56 return state;
57}
58
59} // namespace
60
61namespace rr {
Nicolas Capensc9991d42021-06-16 00:46:28 -040062
Nicolas Capens25c75982022-04-22 14:40:56 -040063void Pragma(BooleanPragmaOption option, bool enable)
Nicolas Capensc9991d42021-06-16 00:46:28 -040064{
Nicolas Capens314508f2021-07-01 01:23:28 -040065 PragmaState &state = ::getPragmaState();
66
Nicolas Capensc9991d42021-06-16 00:46:28 -040067 switch(option)
68 {
69 case MemorySanitizerInstrumentation:
Nicolas Capens314508f2021-07-01 01:23:28 -040070 state.memorySanitizerInstrumentation = enable;
Nicolas Capensc9991d42021-06-16 00:46:28 -040071 break;
72 default:
Nicolas Capens25c75982022-04-22 14:40:56 -040073 UNSUPPORTED("Unknown Boolean pragma option %d", int(option));
Nicolas Capensc9991d42021-06-16 00:46:28 -040074 }
75}
76
Nicolas Capens79d4c6c2022-04-22 17:20:26 -040077void Pragma(IntegerPragmaOption option, int value)
78{
79 PragmaState &state = ::getPragmaState();
80
81 switch(option)
82 {
83 case OptimizationLevel:
84 state.optimizationLevel = value;
85 break;
86 default:
87 UNSUPPORTED("Unknown integer pragma option %d", int(option));
88 }
89}
90
Nicolas Capens25c75982022-04-22 14:40:56 -040091bool getPragmaState(BooleanPragmaOption option)
Nicolas Capensc9991d42021-06-16 00:46:28 -040092{
Nicolas Capens314508f2021-07-01 01:23:28 -040093 PragmaState &state = ::getPragmaState();
94
Nicolas Capensc9991d42021-06-16 00:46:28 -040095 switch(option)
96 {
97 case MemorySanitizerInstrumentation:
Nicolas Capens314508f2021-07-01 01:23:28 -040098 return state.memorySanitizerInstrumentation;
Nicolas Capensc9991d42021-06-16 00:46:28 -040099 default:
Nicolas Capens25c75982022-04-22 14:40:56 -0400100 UNSUPPORTED("Unknown Boolean pragma option %d", int(option));
Nicolas Capensc9991d42021-06-16 00:46:28 -0400101 return false;
102 }
103}
104
Nicolas Capens79d4c6c2022-04-22 17:20:26 -0400105int getPragmaState(IntegerPragmaOption option)
106{
107 PragmaState &state = ::getPragmaState();
108
109 switch(option)
110 {
111 case OptimizationLevel:
112 return state.optimizationLevel;
113 default:
114 UNSUPPORTED("Unknown integer pragma option %d", int(option));
115 return 0;
116 }
117}
118
Nicolas Capens25c75982022-04-22 14:40:56 -0400119ScopedPragma::ScopedPragma(BooleanPragmaOption option, bool enable)
120{
121 oldState = BooleanPragma{ option, getPragmaState(option) };
122 Pragma(option, enable);
123}
124
Nicolas Capens79d4c6c2022-04-22 17:20:26 -0400125ScopedPragma::ScopedPragma(IntegerPragmaOption option, int value)
126{
127 oldState = IntegerPragma{ option, getPragmaState(option) };
128 Pragma(option, value);
129}
130
Nicolas Capens25c75982022-04-22 14:40:56 -0400131ScopedPragma::~ScopedPragma()
132{
Nicolas Capens79d4c6c2022-04-22 17:20:26 -0400133 if(std::holds_alternative<BooleanPragma>(oldState))
134 {
135 auto &restore = std::get<BooleanPragma>(oldState);
136 Pragma(restore.option, restore.enable);
137 }
138 else
139 {
140 auto &restore = std::get<IntegerPragma>(oldState);
141 Pragma(restore.option, restore.value);
142 }
Nicolas Capens25c75982022-04-22 14:40:56 -0400143}
144
Nicolas Capensc9991d42021-06-16 00:46:28 -0400145} // namespace rr