https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88391
Bug ID: 88391 Summary: Request - attribute for adding tags to functions Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: david at westcontrol dot com Target Milestone: --- Sometimes it would be very useful to have "tags" on functions, which can be used to restrict the kinds of functions that can call them or be called by them. I can think of two use-cases from the embedded world, and one more general case: 1. A function that can only be called when interrupts are disabled, has special powers (such as direct access to locked or atomic data, at least on single-core systems) and special responsibilities (it should be fast, should not block, etc.). It should only be called by a function that disables interrupts. 2. A function that needs to run from ram should not call other functions that are not also in ram. This might be for programming code flash, or perhaps to minimise speed variation in a real-time system with slow external flash. 3. A function that should only be called when you have a certain lock or resource. There are many other uses possible uses. I think that a few general attributes could allow this to be handled in the C (and C++) front-end, with the compiler issuing warnings or errors when the "tag" rules are broken. It would not affect code generation, name mangling, etc. - it's just a mechanism to help spot incorrect code. I am not suggesting that we have attributes that actually disable interrupts, or place code in ram (though these might be nice!) - all embedded targets already have mechanisms for that, such as "section" attributes, and we don't need to duplicate functionality that can be handled by a macro or two. My suggestions for function attributes are: 1. __attribute__((tagged("tagname"))) Mark a function as being tagged with "tagname" (or multiple tag names). 2. __attribute__((caller_tag("tagname"))) Mark a function as only being callable by a function with this tag. 3. __attribute__((callee_tag("tagname"))) Mark a function as only being allowed to call functions with this tag. 4. __attribute__((caller_notag("tagname"))) Mark a function as not being callable by a function with this tag. 5. __attribute__((callee_notag("tagname"))) Mark a function as not being allowed to call functions with this tag. There would also need to be a statement attribute: __attribute__((tag("tagname"))) Mark the statement as having this tag (and therefore being allowed to call matching "caller_tag" functions, and not allowed to call matching "caller_notag" functions). Example 1 ========= __attribute__((caller_tag("irq_disabled"), tagged("irq_disabled"))) void criticalFunction(void) { // Some code that should never be interrupted } void normalFunction(void) { // Normal code disableInterrupts(); __attribute__((tag("irq_disabled"))) criticalFunction(); enableInterrupts(); } Example 2 ========= __attribute__((tagged("in_ram")), callee_tag("in_ram"))) __attribute__((section("ramcode"))) void flashCommand(uint32_t cmd) { // Write command to flash programming peripheral } __attribute__((tagged("in_ram")), callee_tag("in_ram"))) __attribute__((section("ramcode"))) void flashErase(void) { flashCommand(0x12345678); } void updateSoftware(void) { downloadNewImage(); flashErase(); flashProgram(); } Example 3 ========= __attribute__((caller_notag("got_lock"))) void getLock(void) { mtx_lock(&mutex); } __attribute__((caller_tag("got_lock"))) void releaseLock(void) { mtx_unlock(&mutex); } __attribute__((caller_tag("got_lock"), tagged("got_lock"))) void accessData(void) { // Use critical data } void normalCode(void) { // Collect data getLock(); __attribute__((tag("got_lock")) { accessData(); releaseLock(); // Still tag "got_lock" } } One big question is the compiler target library. In small embedded systems, apparently simple operations like "x = y / z;" may result in a library call if the processor does not have hardware instructions for the operation. It is important in "callee_tag" functions that any such library calls also issue a warning.