xref: /aosp_15_r20/external/pigweed/pw_build/public/pw_build/linker_symbol.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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