c++gcccompile-timesectionscompiler-specific

In GCC, is there a way to programmatically query which section a variable will be stored in?


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:

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_pointers 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.


Solution

  • 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
    

    Try on godbolt

    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.