-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change-Id: I452f2672ad2b8ed8ea7d6cce721bc1427b83429c Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/242635 Commit-Queue: Jonathon Reinhart <[email protected]> Reviewed-by: Austin Foxley <[email protected]> Presubmit-Verified: CQ Bot Account <[email protected]> Reviewed-by: Wyatt Hepler <[email protected]> Lint: Lint 🤖 <[email protected]>
- Loading branch information
1 parent
f66f4e4
commit 170f745
Showing
7 changed files
with
239 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright 2024 The Pigweed Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy of | ||
// the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations under | ||
// the License. | ||
|
||
#include "pw_build/linker_symbol.h" | ||
|
||
#include "gtest/gtest.h" | ||
|
||
namespace pw { | ||
namespace { | ||
|
||
// These symbols are defined in linker_symbol_test.ld | ||
extern "C" LinkerSymbol<int> FOO_SYM; | ||
extern "C" LinkerSymbol BAR_SYM; // Test template default (uintptr_t) | ||
extern "C" LinkerSymbol<int> NEGATIVE_SYM; | ||
extern "C" LinkerSymbol<char> CHAR_SYM; | ||
|
||
enum class MyEnum { | ||
kValue7 = 7, | ||
}; | ||
extern "C" LinkerSymbol<MyEnum> ENUM_SYM; | ||
|
||
TEST(LinkerSymbolTest, ValueWorks) { | ||
// You can use value() to get the value as the specified type. | ||
auto value = FOO_SYM.value(); | ||
static_assert(std::is_same_v<decltype(value), int>); | ||
EXPECT_EQ(value, 42); | ||
} | ||
|
||
TEST(LinkerSymbolTest, NegativeValueWorks) { | ||
// LinkerSymbol works with negative integers. | ||
EXPECT_EQ(NEGATIVE_SYM.value(), -567); | ||
} | ||
|
||
TEST(LinkerSymbolTest, CharValueWorks) { | ||
// LinkerSymbol works with characters. | ||
EXPECT_EQ(CHAR_SYM.value(), 'a'); | ||
} | ||
|
||
TEST(LinkerSymbolTest, EnumValueWorks) { | ||
// LinkerSymbol works with enums. | ||
EXPECT_EQ(ENUM_SYM.value(), MyEnum::kValue7); | ||
} | ||
|
||
TEST(LinkerSymbolTest, ValueWorksDefaultType) { | ||
// You can use value() to get the value as the default type (uintptr_t). | ||
auto value = BAR_SYM.value(); | ||
static_assert(std::is_same_v<decltype(value), uintptr_t>); | ||
EXPECT_EQ(value, 0xDEADBEEFu); | ||
} | ||
|
||
TEST(LinkerSymbolTest, CStyleCastWorks) { | ||
// You can use a C-style cast, if you insist. | ||
EXPECT_EQ((uintptr_t)&FOO_SYM, 42u); | ||
} | ||
|
||
} // namespace | ||
} // namespace pw |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright 2024 The Pigweed Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
FOO_SYM = 42; | ||
BAR_SYM = 0xDEADBEEF; | ||
NEGATIVE_SYM = -567; | ||
CHAR_SYM = 0x61; /* 'a' */ | ||
ENUM_SYM = 7; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright 2024 The Pigweed Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy of | ||
// the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations under | ||
// the License. | ||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <type_traits> | ||
|
||
#include "lib/stdcompat/bit.h" | ||
|
||
namespace pw { | ||
|
||
/// Represents a symbol provided by the linker, i.e. via a linker script. | ||
/// | ||
/// LinkerSymbol objects are used with linker-provided symbols that don't have | ||
/// storage (which is common), and only provide a value e.g. | ||
/// | ||
/// @code | ||
/// MY_LINKER_VARIABLE = 42 | ||
/// @endcode | ||
/// | ||
/// LinkerSymbol objects are not actual variables (do not have storage) and thus | ||
/// cannot be created; they can only be used with an `extern "C"` declaration. | ||
/// The purpose is to communicate *values* from the linker script to C++ code. | ||
/// | ||
/// Example: | ||
/// | ||
/// @code{.cpp} | ||
/// #include "pw_build/linker_symbol.h" | ||
/// | ||
/// extern "C" pw::LinkerSymbol<uint32_t> MY_LINKER_VARIABLE; | ||
/// | ||
/// uint32_t GetMyLinkerVariable() { | ||
/// return MY_LINKER_VARIABLE.value(); | ||
/// } | ||
/// @endcode | ||
/// | ||
/// @tparam T The type of the value communicated by the linker, defaulting to | ||
/// `uintptr_t`. Must be an integral or enum type, no larger than | ||
/// `uintptr_t`. | ||
template <class T = uintptr_t> | ||
class LinkerSymbol { | ||
public: | ||
LinkerSymbol() = delete; | ||
~LinkerSymbol() = delete; | ||
LinkerSymbol(const LinkerSymbol&) = delete; | ||
LinkerSymbol(const LinkerSymbol&&) = delete; | ||
LinkerSymbol& operator=(const LinkerSymbol&) = delete; | ||
LinkerSymbol& operator=(const LinkerSymbol&&) = delete; | ||
|
||
/// Gets the value of this linker symbol, converted to the specified type. | ||
T value() const { | ||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>); | ||
static_assert(sizeof(T) <= sizeof(uintptr_t)); | ||
return static_cast<T>(raw_value()); | ||
} | ||
|
||
private: | ||
/// Gets the raw value of this linker symbol. | ||
uintptr_t raw_value() const { return cpp20::bit_cast<uintptr_t>(this); } | ||
}; | ||
|
||
} // namespace pw |