• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <cstdint>
17 
18 namespace pw::bloat {
19 
20 // Function providing fundamental C/C++ functions to prevent them from appearing
21 // in size reports. Must be called in binaries which are compared to the bloat
22 // base in order to get accurate reports.
23 void BloatThisBinary();
24 
25 /// A value that can cause all conditions passed to `PW_BLOAT_COND` and
26 /// expressions passed to `PW_BLOAT_EXPR` to be executed. Assign a volatile
27 /// variable to this value and pass it those macros to prevent unwanted compiler
28 /// optimizations from removing code to be measured.
29 [[maybe_unused]] constexpr uint32_t kDefaultMask = ~0u;
30 
31 /// Possibly evaluates a conditional statement as part of a size report.
32 ///
33 /// The `mask` parameter is treated as a bitmap. If the least significant bit is
34 /// set, the condition is evaluated and, if true, the bit is recycled to the
35 /// most significant position. Otherwise, the bit is discarded.
36 ///
37 /// A clever compiler should be kept from optimizing away the conditional
38 /// statements by initializing the `mask` parameter with a volatile variable:
39 ///
40 /// @code{.cpp}
41 ///   volatile uint32_t mask = pw::bloat::kDefaultMask;
42 ///   MyObject my_obj;
43 ///   PW_BLOAT_COND(my_obj.is_in_some_state(), mask);
44 /// @endcode
45 ///
46 /// If a method returns void and is called for its side effects, use
47 /// `PW_BLOAT_EXPR` instead.
48 #define PW_BLOAT_COND(cond, mask)     \
49   do {                                \
50     if ((mask & 1) != 0 && (cond)) {  \
51       mask = (mask >> 1) | 0x8000000; \
52     } else {                          \
53       mask >>= 1;                     \
54     }                                 \
55   } while (0)
56 
57 /// Possibly evaluates an expression as part of a size report.
58 ///
59 /// The `mask` parameter is treated as a bitmap. If the least significant bit is
60 /// set, the expression is evaluated and the bit is recycled to the most
61 /// significant position. Otherwise, the bit is discarded.
62 ///
63 /// A clever compiler should be kept from optimizing away the expression by
64 /// initializing the `mask` parameter with a volatile variable, provided the
65 /// method has some side effect:
66 ///
67 /// @code{.cpp}
68 ///   volatile uint32_t mask = pw::bloat::kDefaultMask;
69 ///   MyObject my_obj;
70 ///   PW_BLOAT_EXPR(my_obj.some_method(), mask);
71 /// @endcode
72 ///
73 /// If a method is const or has no effect beyond its return value, use
74 /// `PW_BLOAT_COND` instead.
75 #define PW_BLOAT_EXPR(expr, mask)     \
76   do {                                \
77     if ((mask & 1) != 0) {            \
78       (expr);                         \
79       mask = (mask >> 1) | 0x8000000; \
80     } else {                          \
81       mask >>= 1;                     \
82     }                                 \
83   } while (0)
84 
85 }  // namespace pw::bloat
86