ldc-developers / ldc

The LLVM-based D Compiler.
http://wiki.dlang.org/LDC
Other
1.21k stars 262 forks source link

Add support for alias attributes #2167

Open danwalmsley opened 7 years ago

danwalmsley commented 7 years ago

I am trying to build startup file for bare metal (STM32)

based on this thread: http://forum.dlang.org/post/uiwtphzmxuqgopbbysht@forum.dlang.org

I have this...

@attribute("weak") @attribute("alias", "defaultExceptionHandler") extern(C) void NMI_Handler();

and then later

@naked extern(C) void defaultExceptionHandler()
{
    while(true)
    {}
}

and it is used like this...

@(section(".interrupt_vector"))
VectorFunc[] interruptVectorTable = [
    cast(VectorFunc)&_stackStart,                                                        /* -16 $0000 Initial Stack Pointer */
    &defaultResetHandler,                                                                    /* -15 $0004 Reset Vector */
    &NMI_Handler,                                                                    /* -14 $0008 Non Maskable Interrupt Vector */

however when linking I get main.o:(.data..constarray+0x8): undefined reference toNMI_Handler'`

any ideas why this hasn't worked?

kinke commented 7 years ago

Well, @attribute("weak") @attribute("alias", "defaultExceptionHandler") extern(C) void NMI_Handler(); doesn't even compile with LDC, these are GDC-specific attributes...

kinke commented 7 years ago

I've seen that you have your own minimal gcc.attribute (derived from GDC I assume). This won't work (the compiler needs to know about them, and LDC only detects those in ldc.attributes). Take a look at the LDC attributes: https://github.com/ldc-developers/druntime/blob/ldc/src/ldc/attributes.d We have @weak (not sure whether the semantics are identical to GDC though) and @section("...") too, but there's no alias and no @naked.

kinke commented 6 years ago

We have @naked now; @alias may be emulatable via pragma(mangle).

japplegame commented 5 years ago

@alias may be emulatable via pragma(mangle).

No, weak alias can not be emulated via pragma(mangle).

This works fine:

extern(C) void DefaultHandler() {...}
@weak extern(C) {
    void ResetHandler() { DefaultHandler(); }
    void NMIHandler() { DefaultHandler(); }
    ...
}

but needs extra codespace for every not overridden handler.

This compiles:

extern(C) void DefaultHandler() {...}
@weak extern(C) pragma(mangle, DefaultHandler.mangleof) {
    void ResetHandler();
    void NMIHandler();
    ...
}

but weak function overriding stops work. Linker ignores all user defined handlers and always links all handlers to DefaultHandler.

We definitely need something like __attribute__ ((weak, alias ("target"))). See https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes

kinke commented 5 years ago

but needs extra codespace for every not overridden handler

Even with --gc-sections? It shouldn't when moving each default handler into its own object file, but I get that that's not ideal.

So how would the preferred syntax be? Something like

extern(C):

void DefaultHandler() {}

@weakAlias(DefaultHandler.mangleof)
{
    void ResetHandler();
    void NMIHandler();
}
japplegame commented 5 years ago

but needs extra codespace for every not overridden handler

Even with --gc-sections? It shouldn't when moving each default handler into its own object file, but I get that that's not ideal.

How would that help? Interrupt handlers are used to fill the interrupt vector. Therefore, the linker cannot remove default handlers.

So how would the preferred syntax be? Something like

extern(C):

void DefaultHandler() {}

@weakAlias(DefaultHandler.mangleof)
{
    void ResetHandler();
    void NMIHandler();
}

Looks good.

kinke commented 5 years ago

How would that help? Interrupt handlers are used to fill the interrupt vector. Therefore, the linker cannot remove default handlers.

You were worried about code size for the extra tiny default wrappers, e.g., void ResetHandler() @weak { DefaultHandler(); }. If it's in its own object file and the user overrides it at link time with a custom implementation, it shouldn't be linked in, and you'll save the couple of bytes. My understanding at least, but I've never dealt with interrupt handlers, and only needed @weak once so far, in the DMD frontend itself. Edit: Ah sorry, you were worried about the code size of the non-overridden wrappers. Just out of curiosity, how many bytes are we talking about here? ;)

japplegame commented 5 years ago

Edit: Ah sorry, you were worried about the code size of the non-overridden wrappers. Just out of curiosity, how many bytes are we talking about here? ;)

Several bytes for every non-overridden handler. In most cases, it is 100-200 bytes in total. :) I should confess, I am more concerned about the fact of such non-optimality, than about the size of the firmware. :)