1 // Copyright 2024 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 #include <type_traits> 18 19 #include "lib/stdcompat/bit.h" 20 21 namespace pw { 22 23 /// Represents a symbol provided by the linker, i.e. via a linker script. 24 /// 25 /// LinkerSymbol objects are used with linker-provided symbols that don't have 26 /// storage (which is common), and only provide a value e.g. 27 /// 28 /// @code 29 /// MY_LINKER_VARIABLE = 42 30 /// @endcode 31 /// 32 /// LinkerSymbol objects are not actual variables (do not have storage) and thus 33 /// cannot be created; they can only be used with an `extern "C"` declaration. 34 /// The purpose is to communicate *values* from the linker script to C++ code. 35 /// 36 /// Example: 37 /// 38 /// @code{.cpp} 39 /// #include "pw_build/linker_symbol.h" 40 /// 41 /// extern "C" pw::LinkerSymbol<uint32_t> MY_LINKER_VARIABLE; 42 /// 43 /// uint32_t GetMyLinkerVariable() { 44 /// return MY_LINKER_VARIABLE.value(); 45 /// } 46 /// @endcode 47 /// 48 /// @tparam T The type of the value communicated by the linker, defaulting to 49 /// `uintptr_t`. Must be an integral or enum type, no larger than 50 /// `uintptr_t`. 51 template <class T = uintptr_t> 52 class LinkerSymbol { 53 public: 54 LinkerSymbol() = delete; 55 ~LinkerSymbol() = delete; 56 LinkerSymbol(const LinkerSymbol&) = delete; 57 LinkerSymbol(const LinkerSymbol&&) = delete; 58 LinkerSymbol& operator=(const LinkerSymbol&) = delete; 59 LinkerSymbol& operator=(const LinkerSymbol&&) = delete; 60 61 /// Gets the value of this linker symbol, converted to the specified type. value()62 T value() const { 63 static_assert(std::is_integral_v<T> || std::is_enum_v<T>); 64 static_assert(sizeof(T) <= sizeof(uintptr_t)); 65 return static_cast<T>(raw_value()); 66 } 67 68 private: 69 /// Gets the raw value of this linker symbol. raw_value()70 uintptr_t raw_value() const { return cpp20::bit_cast<uintptr_t>(this); } 71 }; 72 73 } // namespace pw 74