I've run into another situation that seems to require a change to mspgcc's lower-level interfaces. Here's the background, rationale, and impact. This affects you if you override certain functions like _reset_vector__, use the "reserve" function attribute (RESERVE_MEM), use the -mno-init-stack or -mendup-at= compiler options, or explicitly use the global ctors/dtors lists. Or if you rely on there being symbols like .L__FrameSize_FUNCTION and .L__FrameOffset_FUNCTION being available.
Please let me know if you have objections to what's described below and we'll try to find an accommodation. Background ========== CRT refers to "C run-time", and means the code that gets executed before and after main(), in support of language-specific constructs and platform initialization. Historically, these routines were defined in msp430-libc. They've now moved to gcc, decoupling it from msp430-libc so that alternative libc implementations can be used and ensuring consistency between the compiler and the runtime system. How it is in mspgcc4 (which is mostly how it was in mspgcc3): Before main, the following are executed in a series of linker sections numbered .init0 through .init9: _reset_vector__ : Invokes the following in order. If you override this, the rest of the startup is also eliminated unless you put each piece back. __init_stack : Set the stack pointer to the value of the linker symbol __stack, which defaults to top of RAM. __low_level_init : Disables the watchdog __do_copy_data : Copies initialized data from ROM to RAM __do_clear_bss : Zeroes the remainder of RAM __do_global_ctors : Old-style C++ constructors, calling in turn a series of addresses stored between __ctors_start and __ctors_end. __jump_to_main : Jumps to main The main routine is treated specially: in its prologue, it resets the stack pointer (unless -mno-stack-init was given), optionally reserving additional space with the "reserve" function attribute. In its epilogue, it jumps to __stop_progExec__, or the symbol given by the -mendup-at= compiler option, instead of returning. The default __stop_progExec__ executes the following in a series of sections numbered .fini9 to .fini0: __do_global_dtors : Old-style C++ destructors, calling in turn a series of addresses stored between __dtors_start and __dtors_end. _endless_loop__: Infinite loop to prevent further operation Each of the symbols described above can be overridden by the user by re-defining them. Somewhat related to this, the existing epilogue/prologue code includes generation of symbols .L__FrameSize_FUNCTION and .L__FrameOffset_FUNCTION, where "FUNCTION" is replaced by the name of the corresponding function. The former value attempts to define the size of the stack frame within the function; the latter attempts to indicate the position of stack-saved arguments relative to the stack pointer. Problems ======== The showstopper that started all this is that, in gcc 4.5.x and higher, special-casing the prologue/epilogue code for main() prevents generating debug information with the -g option: the common dwarf2 code in gcc can't process prologue and epilogue code that contains symbol references (for the initial stack location) and jumps (to -mendup-at) instead of returns, and the compiler aborts. The special-casing where main gets to redefine the stack pointer also interferes with the environment for C++ constructors that get executed before main. The .L__FrameSize_FOO and .L__FrameOffset_FOO values cause problems because the user believes that they can be used relative to r1 (the stack pointer) to access data. In 99% of the common cases, it'll work, which is why people have gotten away with this for things like GET_FRAME_ADDRESS() and BIC_SR_IRQ(). In other cases, it won't, and it'll be a bear to figure out why. The compiler is perfectly within its rights to temporarily adjust the stack pointer at various points in the code---e.g., when a statement block declares a dynamically-sized auto-class array, the user calls alloca(3), or stack space has to be reserved for function arguments or return values. None of that is reflected in those compile-time constants. As a minor irritant, mspgcc is the only msp430 toolchain I know that immediately disables the watchdog, pretending it doesn't exist. After nearly a decade of this the default behavior can't change, but it can at least be controlled. Proposed Solution ================= Most of the existing CRT functions will be retained. __do_global_ctors and __do_global_dtors will go away, being replaced by the gcc target-independent approach to maintain and invoke those function lists. Users who need special support for things to be executed before or after main but don't want to completely replace _reset_vector__ or __stop_progExec__ can put them into one of the unused init or fini sections. C++ users won't need to do anything special. main() will no longer re-initialize the stack pointer. That will always be done by the __init_stack routine. The -mno-init-stack option goes away. The "reserve" function attribute, which only had meaning for main, will be removed. Space at the top of RAM is reserved by overriding __init_stack. An example of doing this will be added to the manual. main() will no longer jump to some arbitrary location instead of returning. It will return, and having done so will fall-through to the .fini9 section. Consequently, the -mendup-at= option will be removed. Override __stop_progExec__ if you want it to do something else. .L__FrameSize_FOO and .L__FrameOffset_FOO go away. Every case I know of where they might be used has been replaced by built-in functions which the compiler guarantees will work, regardless of which bizarre combination of function attributes and code generation options has been chosen. These include: __builtin_frame_pointer : GCC standard builtin __builtin_return_address : GCC standard builtin __bi[cs]_sr_irq : adjust the value of the status register in function that uses reti to return. The macros currently defined in msp430-libc's iomacros.h which used to use these constants will be re-defined in terms of the builtins. If you have some other reason why you need those constants, please explain. A new option -menable-watchdog will be added which change which libcrt0.a file gets linked in. The default will be the existing approach that disables the watchdog on reset; an alternative will leave it enabled (and ensure it gets kicked at appropriate stages during the initialization). Caveat ====== Some of what I've described above has been done and validated; some of it is just a plan. Details may change as I get into the implementation. Comments? Peter ------------------------------------------------------------------------------ Colocation vs. Managed Hosting A question and answer guide to determining the best fit for your organization - today and in the future. http://p.sf.net/sfu/internap-sfd2d _______________________________________________ Mspgcc-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mspgcc-users
