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