I'm working with some code that targets an unusual embedded system that requires distinct processor instructions to read from its read-only memory.
For variables to be placed in said read-only memory, they must be marked with an attribute that places them in a designated section whose contents will be placed into read-only memory.
It would be useful to be able to programmatically determine which section a variable is stored in so that I can determine, at compile-time, which variables are going to be stored in RAM (and thus can use ordinary pointer dereferencing and reference reading) and which variables are going to be stored in ROM (and thus require specialised access code written in assembly).
Having access to such a feature would allow me to do something like:
template<typename Type>
struct data_pointer
{
Type * pointer;
data_pointer(Type * pointer, bool) :
pointer { pointer } {}
// Non-const data cannot be readonly
Type & operator *()
{
return *pointer;
}
};
template<typename Type>
struct data_pointer<const Type>
{
const Type * pointer;
bool is_readonly;
data_pointer(const Type * pointer, bool is_readonly) :
pointer { pointer },
is_readonly { is_readonly }
{}
// Const data might be in RAM or ROM
const Type operator *()
{
return (is_readonly ? *pointer : readonly_dereference(pointer));
}
};
#define make_data_pointer(object) \
(data_pointer(&object, is_in_readonly_section(object)))
Where:
readonly_dereference
is the mechanism by which a pointer to a value in the read-only memory area is read.is_in_readonly_section(object)
is the hypothetical compile-time predicate that would be necessary to make the mechanism seamless.Does GCC have anything akin to this hypothetical is_in_readonly_section
compile-time predicate, or am I out of luck?
I could manage without it, but not having it means that the end user would be responsible for ensuring that their data_pointer
s point to the right kind of memory, which is liable to be a far more error-prone scenario than if the compiler could be made to bear the burden.
GCC provides __builtin_has_attribute
which can do this.
#include <iostream>
int x;
int y __attribute__((section("foobar")));
int main() {
std::cout << "x:" << __builtin_has_attribute(x, section("foobar")) << "\n";
std::cout << "y:" << __builtin_has_attribute(y, section("foobar")) << "\n";
}
prints
x: 0
y: 1
The result of __builtin_has_attribute
behaves as an integer constant expression, so can be used to select alternatives at compile time.
Of course, this only works if a declaration of y
with the section("foobar")
attribute is in scope.