Minimal linker script for cortex M3 and M4 using gcc for c language applications
Hi list!, I'm working in a project using gcc to develop applications using c language for embedded systems based on ARM Cortex M3 and M4. I have found some linker script used by commercial tools like lpcxpresso (from NXP) or Code Composer Studio (from TI) and others frecuently used for other developers with a lot of entries not documented. Where can I find the minimal entries required to make a linker script for c language applications using segments RAM and FLASH memories? As example (because I think my english is not so good) look at the sample code attached. Where can I find information about the entries marked with ???-> Thanks a lot! Sergio MEMORY { flash(rx) : ORIGIN = 0, LENGTH = 512K ram(wx) : ORIGIN = 0x2200, LENGTH = 64K-0x200 } SECTIONS { . = 0; .text : { KEEP(*(.isr_vector)) *(.text) *(.text.*) ???-> *(.gnu.linkonce.t.*) ???->*(.glue_7) ???->*(.glue_7t) ???->*(.gcc_except_table) ???->*(.gcc_except_table.*) ???->*(.ARM.extab*) ???->*(.gnu.linkonce.armextab.*) . = ALIGN(4); *(.rodata) *(.rodata.*) ???->*(.gnu.linkonce.r.*) } > flash ???->__exidx_start = .; ???->.ARM.exidx : ???->{ ???->*(.ARM.exidx* .gnu.linkonce.armexidx.*) ???->} > flash ???->__exidx_end = .; . = ALIGN(8); _etext = .; .data : ALIGN(8) { _data = .; *(.data) *(.data.*) ???->*(.gnu.linkonce.d.*) . = ALIGN(8); _edata = .; } > ram AT > flash .bss : { _bss_start = .; *(.bss) *(.bss.*) ???->*(.gnu.linkonce.b.*) . = ALIGN(8); _bss_end = .; } > ram _end = .; PROVIDE(end = .); }
Extension for a throw-like C++ qualifier
Dear, I felt a bit disappointed while learning about the throw qualifier. I think a more useful qualifier can be created in order to describe the possible exceptions a method can throw, in the following way: int TheClass::exceptMethod() _throw TheException { throw TheException(); } In this case, the gcc would check at runtime that the only exception the method exceptMethod may throw is TheException. Moreover int TheClass::wrongMethod() _throw () { exceptMethod(); } should yield an error, since the exceptMethod() may throw the exception TheException(), but the qualifier _throw () indicates that no exception can arise from calling wrongMethod(). However int TheClass::correctMethod() _throw() { try { exceptMethod() } catch (TheException) { doSomething(); } } should correct, since the exception is catched. I think that, if it is pessimistically supposed that every exception not enclosed into a try { } catch { } block may be thrown, the check can be done at runtime. The overall idea is, of course, to give information to the caller about the exceptions it must handle. I think that this extension would worth the while. Any ideas? Cheers, Sergio
Re: Extension for a throw-like C++ qualifier
On 3/30/07, Mike Stump <[EMAIL PROTECTED]> wrote: ? Just what did you want that isn't in the standard again? Is the feature you want just static checking for exception specifications at compile time? Yes, it is. Please read "compile time" when it says "runtime". The errors mentioned are compile errors, not runtime errors. I don't know if it is exactly "static checking", because some programs yielding compile errors with this feature should not yield runtime errors without this feature. As an example, int TheClass::wrongMethod() _throw () { if(0) throw TheException(); } would yield a compile error, but using the standard throw does not generate a runtime error. In addition, I think that it is not convenient to perform the check as a feature for the existing throw. I think that it is convenient to create a new keyword (which I oh-so-cleverly named _throw) and allow such an extension for the language which something like -fallow_throw. Cheers, Sergio On 3/30/07, Mike Stump <[EMAIL PROTECTED]> wrote: On Mar 30, 2007, at 11:05 AM, Sergio Giro wrote: > int TheClass::exceptMethod() _throw TheException { > throw TheException(); > } > > In this case, the gcc would check at runtime that the only exception > the method exceptMethod may throw is TheException. It does. > Moreover > > int TheClass::wrongMethod() _throw () { > exceptMethod(); > } > > should yield an error, It does, through, at runtime. > should correct, since the exception is catched. It is. > I think that, if it is pessimistically supposed that every exception > not enclosed into a try { } catch { } block may be thrown, the check > can be done at runtime. It is. > The overall idea is, of course, to give information to the caller > about the exceptions it must handle. Right, exception specifications do. > I think that this extension would worth the while. Any ideas? ? Just what did you want that isn't in the standard again? Is the feature you want just static checking for exception specifications at compile time?
Re: Extension for a throw-like C++ qualifier
Maybe that the option you suggest This is best done with something like -fstatic-exception-specifications or maybe - Wexception-specifications -Werror. is ideal, but it seems to me not practical at all. Every stuff using the throw qualifier as specified in the standards will not work. If an inline method in a standard header is theInlineMethod (void) throw () { throw theException(); }; this will not even compile... Of course, using an extension as the one I propose, some of the standard methods must be wrapped if you want to use the new qualifier in order to track the possible exceptions that the methods may arise, but I think it is quite more practical to wrap such methods than to modify the headers... In addition, the semantic meaning is not the same: a throw (a,b,c) qualifier indicates that you are able only to catch the exceptions a, b and c, and that every other exception will be seen as std::unexpected. Nevertheless, a _throw(a,b,c) qualifier should indicate that the only exceptions that can arise are a, b and c . With respect to this: If you wanted finer control, having an inheritable attribute that says, please statically check exception specifications for all member functions in this class and/ or on the function would be better than replicating the entire mechanism. I think that a lot of information can be obtained by using existing mechanisms. The calculation of the exceptions a module may arise under pessimistic assumptions is rather easy, if you don't allow template exceptions to be used in the _throw qualifier. I think that the hard step is to put it into gcc. I will be grateful for any advise on how to start looking add in order to implement this new feature. Cheers, Sergio On 3/30/07, Mike Stump <[EMAIL PROTECTED]> wrote: On Mar 30, 2007, at 11:59 AM, Sergio Giro wrote: > The errors mentioned are compile errors, So, you want a strict subset of the language standard. This is best done with something like -fstatic-exception-specifications or maybe - Wexception-specifications -Werror. If you wanted finer control, having an inheritable attribute that says, please statically check exception specifications for all member functions in this class and/ or on the function would be better than replicating the entire mechanism.
Re: Extension for a throw-like C++ qualifier
On Apr 2, 2007, at 2:32 AM, Brendon Costa wrote: I have for a while been working on a tool that performs static analysis I agree that Brendon's project is a very good idea, but I still have an argument against it: having such an analysis into gcc forces the gcc development community to maintain the code performing the analysis. Having this analysis outside gcc makes it less likely to remain in time. If I start a huge project, I would prefer to wrap external functions into try { } catch(...) blocks (in a huge project, the time spent by this task is negligeable) instead of relying on an external tool... I agree that edoc++ is very useful (particularly, generating documentation for Doxygen is a very nice issue!), but I keep interested to implement this feature inside gcc. I write here because I am looking forward for your discouraging comments! Maybe you can convince that this is not useful... If you consider this analysis to be useful, I will be grateful for any ideas concerning where and how to start looking in order to implement the analysis. Cheers, Sergio On 4/2/07, Mike Stump <[EMAIL PROTECTED]> wrote: Ah, yeah, that I suspect would be a even better way to do this... Itt would be nice if gcc/g++ had more support for static analysis tools... Maybe with LTO.
Inclusion in an official release of a new throw-like qualifier
Hello, I started a thread about the possible development of a throw-like qualifier for C++ which may statically check that the only possible exceptions are those declared in the qualifier (please see the corresponding thread: http://gcc.gnu.org/ml/gcc/2007-03/msg01162.html ). It would be my first contribution to a GNU project, and I would like to know how likely this extension to the language is to be included in an official release. Does it depend only in the quality of the code, tests, etc. or there are additional factors? The people involved in the thread do not detered me to carry out the extension (but they were only two person :D ). My main purpose is to have such a static check _inside_ gcc, in order to be sure that this extension will be maintained and available in the future. If it is not likely to be included in an official release, I prefer to contribute to eDoc++ (edoc.sourceforge.net), an (almost) existing tool which performs the test "outside" gcc. All the best, Sergio
Re: Inclusion in an official release of a new throw-like qualifier
I perceived that many people think that the throw qualifiers, as described by the standard, are not useful, as an example, I quote the Boost Exception-specification rationale: Although initially appealing, an exception-specification tends to have consequences that require very careful thought to understand. The biggest problem with exception-specifications is that programmers use them as though they have the effect the programmer would like, instead of the effect they actually have. (thanks to Scott McMurray for this quote) Then, what is the best way to have a reliable description of the exceptions a method can throw? (Reliable in the sense that this description can be checked by the compiler). Static checks for the existing qualifier are not practical, since legacy code not using the qualifier in the new way will not compile. That is what I meant when I said: > theInlineMethod (void) throw () { throw theException(); }; > this will not even compile... Jason Merrill wrote: I doubt that anything like this appears in the standard headers. (Of course, the method I have write is a toy example). Note that, in this case, the legacy code needs to be _modified_, and cannot be wrapped. Since it is quite impractical, I think that it is necessary to distinguish the qualifier meaning "Not other exceptions than a, b and c can be catched" (i.e., the qualifier as described by the standard) from the qualifier meaning "This method throws no other exceptions than a, b, c". In order to distinguish both qualifiers, a new qualifier can be added. Another option to allow such a distinction is to use the word "static" before the throw qualifier. Of course, the new qualifier (or the word static) will not be used in legacy code. For programs using legacy code, the methods belonging to the legacy code must be wrapped into try/catch blocks (we cannot ensure what the exceptions thrown by such methods are, since the throw qualifier is used in the way described by the standard). Furthermore, gcc internals currently don't support much in the way of inter-procedural analysis, and none between routines in separate modules. It is not inter-procedural analysis: you only need the prototypes... If you have a prototype void method() _throw foo; and after that prototype you have a method void wrongMethod() _throw () { instance.method(); }; This method can be signaled as incorrect, since method() may throw a foo exception. However, void rightMethod() _throw () { try {instance.method();} catch(foo) { return; } }; can be signaled as correct, since it is known that the only exception that can be thrown by method() is foo. During the compilation of method(), it is checked that every throw instruction throws only foo exceptions (and that every method invoked --as described by the prototypes-- throws only foo exceptions), or that the other exceptions are enclosed into corresponding try/catch blocks. Hence, note that the analysis can be performed using the code of the method and the previous prototypes. I'm strongly opposed to adding a new qualifier with slightly different semantics from one already in the language. I agree that this may cause some confusion. What about the "static throw" qualifier? In addition, in order to ensure that the code with the extension will compile in other compilers, a macro STATIC_THROW can be defined, which expands either to "static throw", if the extension is supported, or to "throw" if it is not. With respect to this, > In addition, the semantic meaning is not the same: a > throw (a,b,c) qualifier indicates that you are able only to catch the > exceptions a, b and c, and that every other exception will be seen as > std::unexpected. Nevertheless, a > _throw(a,b,c) qualifier should indicate that the only exceptions that > can arise are a, b and c. But in both cases, the only exceptions that can leave the function are a, b and c. I don't see what your extension would add that wouldn't also be provided by -Wexception-specs. Yes, the only exceptions that can leave the function are a, b and c, but, in addition to the exceptions, you may get a nasty call to unexpected()... The idea is that if you can write int main() _throw () { yourCode(); } and your code compile, you will not have unexpected exceptions thrown during the execution of your program. Moreover, you have better control of the exceptions that can be thrown in every point of the execution... All the best, Sergio
Re: Inclusion in an official release of a new throw-like qualifier
With respect to this: Jason Merrill wrote: Yes. But that's not a reason to add a slightly different non-standard feature that would require people already using standard exception specifications to rewrite everything. That's just a non-starter. Maybe I missed some point: why everything should be rewritten? As far as I understand, nothing needs to be rewritten. The programs using the standard qualifier throw will not be aware of the new feature, and they will compile and run as if the feature were not implemented. The standard throw qualifier must be kept, and a new qualifier (static throw, or _throw) would be added with the new meaning. If you like it, you can use it by specifying -fallow_static_throws. If you don't like it, don't use the -fallow... and your code will be standard and it will have the standard semantics... Moreover, if you use the -fallow_static_throws the code not using "static throw" or "_throw" will compile and run as if the feature were not implemented... The only bad thing here is that you have two qualifiers having similar meanings... But I think it must be that way in order to _avoid_ rewriting code. However, a flag to perform static checking of standard exception specifications and warn about violations is very likely to be included. The point here is that, in order to do this, you need interprocedural analysis. If you have qualifiers as the one I describe, you can perform the check by merely using the prototypes... I agree with Jason that an extension which implies rewriting everything is not very likely to be included, but it is not case. So, what do you think now? Cheers, Sergio
Re: Inclusion in an official release of a new throw-like qualifier
Mike Stump wrote: Let me try again. The standard way to add a new qualifier in g++, is to add it in an attribute, please do that. OK, I agree. Let's say that a method will be declared as int method() throw(std::exception) __attribute__((static_exc_check)); (this is intended to have the same meaning of int method() _throw(std::exception); as explained before). With respect to this: > The point here is that, in order to do this, you need > interprocedural analysis. You've not yet grasped they are isomorphic forms. If the above is true, then then below is wrong. If the below is not wrong, then the above must be wrong. Your pick. > If you have qualifiers as the one I describe, you can perform the > check by merely using the prototypes... This check using prototypes is not more interprocedural than type-checking is... If your definition of interprocedural analysis includes type-checking, OK, I agree... In order to type check a method m, you need the prototypes of the methods m calls to. In addition, when you check the code of a method m, you compare the return type of the code with the return type in the prototype. It works the same way for the static check of exception specifications...
Re: Inclusion in an official release of a new throw-like qualifier
Brendon's point is a good one: It avoids having to define special attributes in the code, the only difference is the set of command line flags you pass to the compiler. It does however mean that you cant provide function level "enable/disable of static checking". I.e. It will check for all functions whose implementation you find in the given translation unit. Here we have a trade-off. Either a new attribute is added, which allows function level "enable/disable of static checking" (but this requires adding a new attribute) or a flag is added to the compiler, thus disallowing function level enabling. I think that finer control of enabledness is a must in order to avoid warnings from external headers... Maybe there is another way to switch between static/runtime checking (I have seen that pragma's have even worse reputation than attributes, so I do not even mention them :D ) Using grep -v to eliminate warnings (as indicated for Weffc++) sounds not very elegant to me... With respect to Aaron: This is a challenge to implement, as it needs to use non-intrusive decorators and heuristics to allow the user to indicate cases where exceptions logically won't propagate, even though they 'theoretically could.' Complete static checking would end up being the equivalent of -Weffc++: completely useless. OK, but let me say that I am trying to accomplish a much more humble task... At the beginning, the only information used will be the one provided by programmer in the prototypes. Maybe someone later can save the programer to write unuseful code. It seems to me that fully accomplishing what you are talking about needs an algorithm for the halting problem, and I plan to have such an algorithm not until 2009 :D . All the best, Sergio
Is the GCC optimazer too smart?
Hi All, I just joined the list and I'm not a compiler guru, so I'd like "the list" opinion on a behavior I notice today. Not sure it is really a bug, so do not want to directly open a bug in the bugzilla repository. Consider the below sample code: #include int main(int argc, char** argv) { const int i = 0; printf("i: %d\n", i); foo(&i); printf("i: %d\n", i); return 0; } I compiled the above code without any optimization flag, and with the -O3 flag. [bash] sborg...@ree> gcc gcc_const_optimazer_bug.c -o gcc_const_optimazer_bug gcc_const_optimazer_bug.c: In function `main': gcc_const_optimazer_bug.c:18: warning: passing arg 1 of `foo' discards qualifiers from pointer target type [bash] sborg...@ree> ./gcc_const_optimazer_bug i: 0 i: 42 [bash] sborg...@ree> gcc -O3 gcc_const_optimazer_bug.c -o gcc_const_optimazer_bug gcc_const_optimazer_bug.c: In function `main': gcc_const_optimazer_bug.c:18: warning: passing arg 1 of `foo' discards qualifiers from pointer target type [bash] sborg...@ree> ./gcc_const_optimazer_bug i: 0 i: 0 Now my question is: is it correct that the compiler enforces the constantness of the variable, even tought it states in the warning that the const qualifier has been discarded? Best Regards Sergio -- preferisco ammazzare il tempo, preferisco sparare cazzate, preferisco fare esplodere una moda, preferisco morire d'amore. (Caparezza)
porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!
Hi everyone, I am porting GCC to a custom 16-bit microcontroller with very limited addressing modes. Basically, it can only load/store using a (general purpose) register as the address, without any offset: LOAD (R2) R1; load R1 from memory at address (R2) STORE R1 (R2) ; store R1 to memory at address (R2) As far as I can understand, this is more limited than the current architectures supported by GCC that I found in the current gcc/config/*. Since for my port I started modifying a MIPS target (from the tutorials by IIT Bombay http://www.cse.iitb.ac.in/grc/ - great work guys!), the GCC still generates code like: sw R15, 0(R13) sw R13, -2(R13) sw R14, -4(R13) ... lw R14, -4(R13) lw R15, 0(R13) Now, in order to restrict the addressing mode, I want to force GCC to compute the address and store it in a register, then generate the instructions above to LOAD/STORE in memory. Thus I tried to fiddle with LEGITIMATE_ADDRESS() and LEGITIMIZE_ADDRESS(), but the compilation of a simple C program like: void foobar(int par1, int par2, int parN) { int a, b, c; a = -1; b = -65535; c = 0xabcd; } fails with foobar7.c:11: internal compiler error: in change_address_1, at emit-rtl.c:1800 Please submit a full bug report, The same program gets compiled with the lw/sw above if I replace 0 with 1 in legitimate_address() below, at the comment /* reject/accept*/. What should I do? How the addressing mode(s) are managed in the md files and the LEGITxxx_ADDRESS() macros ? The GCC manual is not very clear on this... Is there any other architecture/documentation I should look at ? Thanks, Sergio === Here follows a fragment of my micro.c with the C implementations of the LEGITIMATE_ADDRESS() and LEGITIMIZE_ADDRESS() macros: - int legitimate_address2(enum machine_mode MODE,rtx X) { rtx op1,op2; if(CONSTANT_ADDRESS_P(X)) { return 1; } if(GET_CODE(X)==REG && non_strict_base_reg(REGNO(X))) { return 1; } if(GET_CODE(X)==PLUS) /* is it offset+(Rx) ?! */ { puts ("GET_CODE(X)==PLUS "); op1=XEXP(X,0); op2=XEXP(X,1); if(GET_CODE(op1)==REG && CONSTANT_ADDRESS_P(op2) && non_strict_base_reg(REGNO(op1))) { return 0; /* reject / accept */ } if(GET_CODE(op2)==REG && CONSTANT_ADDRESS_P(op1) && non_strict_base_reg(REGNO(op2))) { return 0; /* reject / accept */ } } /* reject all other cases, too */ puts ("legitimate_address2() - end - ret 0/NO"); return 0; } rtx legitimize_address(rtx X,rtx OLDX, enum machine_mode MODE) { rtx op1,op2,op; op=NULL; if(memory_address_p(MODE,X)) return X; if(GET_CODE(X)==MEM && !no_new_pseudos) op = force_reg(MODE,X); else if ( GET_CODE(X)==PLUS && !no_new_pseudos) { puts("GET_CODE(X)==PLUS && !no_new_pseudos !"); op1=XEXP(X,0); op2=XEXP(X,1); if(GET_CODE(op1)==REG && !CONSTANT_ADDRESS_P(op2)) { op=force_reg(MODE,X); } else if(GET_CODE(op2)==REG && !CONSTANT_ADDRESS_P(op1)) { op=force_reg(MODE,X); } else /* HACK */ { op=force_reg(MODE,X); } - /* Here is another HACK attempt, now disabled (commented), inspired by http://gcc.gnu.org/ml/gcc/2001-07/msg01513.html, but this is not working, either */ else if ( (GET_CODE (op1)== REG) && (GET_CODE (op2) == CONST_INT) ) { op1 = force_reg (MODE, op1); op = force_reg (MODE, gen_rtx_PLUS (MODE, op1, op2)); } - } if(op!=NULL && memory_address_p(MODE,op)) { return op; /* if we rewrote the expression */ } return X; /* otherwise original */ } - Here is a fragment of "micro.md" with the definitions of the "movXX", load and store patterns: (define_expand "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" "") )]
Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!
Gabriel Paubert wrote: > On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote: >> Hi everyone, >> >> I am porting GCC to a custom 16-bit microcontroller with very limited >> addressing modes. Basically, it can only load/store using a (general >> purpose) register as the address, without any offset: >> >> LOAD (R2) R1; load R1 from memory at address (R2) >> STORE R1 (R2) ; store R1 to memory at address (R2) >> >> As far as I can understand, this is more limited than the current >> architectures supported by GCC that I found in the current gcc/config/*. > > The Itanium (ia64) has the same limited choice of addressing modes. > > Gabriel Thanks Gabriel. I dived into the ia64 md, but it is still unclear to me how the various parts (macros, define_expand and define_insn in MD etc.) work together to force the computation of a source/dest address plus offset into a register... can anyone help me with this ? Thanks, Sergio
Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!
Now my GO_IF_LEGITIMATE_ADDRESS refuses anything that is not a REG or a CONSTANT_ADDRESS: int legitimate_address1(enum machine_mode MODE,rtx X) { if(CONSTANT_ADDRESS_P(X)) return 1; if(GET_CODE(X)==REG && is_base_reg(REGNO(X))) return 1; return 0; /* fails everything else */ } /* this is the strict version, the non strict version is similar */ but GCC (4.0.2, just in case the version is relevant) still aborts the compilation. Then I found this wiki note about forcing complex addresses into registers: http://gcc.gnu.org/wiki/WritingANewBackEnd ... rtx copy_addr_to_reg (rtx x) Equivalent to copy_to_mode_reg (Pmode, x). For example, this function can be used to compute a complex address X in a register for an instruction which supports only register indirect addressing. See also replace_equiv_address() below. ... Thus I changed in the .md file the movXX RTL expand macro to force any MEM expression into a register: (define_expand "movhi" /* my micro is 16 bit... */ [(set (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" "") )] "" { if(!no_new_pseudos && GET_CODE(operands[0])==MEM) { if( /* addr in operands[0] == base reg + offset */ ) operands[0] = copy_addr_to_reg ( operands[0] ); } ) The GCC still fails to generate the assembly code to do the arithmetic computation of the baseReg+offset-->tempReg, and then use (tempReg) as address. Note that with the current MD GCC is able to generate simple sums like R1 = R2 + R3 and R1 = R2 + IMM, thus the basic math to compute an address is there. Any suggestion on what I am doing wrong ? Sergio Michael Hope wrote: > Hi Sergio. My port has similar addressing modes - all memory must be > accessed by one of two registers and can only be accessed indirectly, > indirect with pre increment, and indirect with post increment. The > key is GO_IF_LEGITIMATE_ADDRESS and the legitimate address helper > function. Mine looks like this: > > /* Return 1 if the address is OK, otherwise 0. >Used by GO_IF_LEGITIMATE_ADDRESS. */ > > bool > tomi_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, >rtx x, >bool strict_checking) > { > /* (mem reg) */ > if (REG_P (x) > && tomi_reg_ok (x, strict_checking) > ) > { > return 1; > } > > if (GET_CODE(x) == PRE_DEC) > { > ... > } > > if (GET_CODE(x) == POST_INC) > { > ... > } > > return 0; > } > > tomi_reg_ok returns true if x is any register when strict checking is > clear and true if x is one of my addressing registers when strict > checking is set. > > GCC will feed any memory accesses through this function to see if they > are directly supported, and if not it will break them up into > something smaller and try again. > > Hope that helps, > > -- Michael > > > 2010/1/26 Sergio Ruocco : >> Gabriel Paubert wrote: >>> On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote: >>>> Hi everyone, >>>> >>>> I am porting GCC to a custom 16-bit microcontroller with very limited >>>> addressing modes. Basically, it can only load/store using a (general >>>> purpose) register as the address, without any offset: >>>> >>>> LOAD (R2) R1; load R1 from memory at address (R2) >>>> STORE R1 (R2) ; store R1 to memory at address (R2) >>>> >>>> As far as I can understand, this is more limited than the current >>>> architectures supported by GCC that I found in the current gcc/config/*. >>> The Itanium (ia64) has the same limited choice of addressing modes. >>> >>> Gabriel >> Thanks Gabriel. >> >> I dived into the ia64 md, but it is still unclear to me how the various >> parts (macros, define_expand and define_insn in MD etc.) work together >> to force the computation of a source/dest address plus offset into a >> register... can anyone help me with this ? >> >> Thanks, >> >>Sergio >>
Re: porting GCC to a micro with a very limited addressing mode --- success with LEGITIMATE / LEGITIMIZE_ADDRESS, stuck with ICE !
Michael Hope wrote: > Hi Sergio. Any luck so far? Micheal, thanks for your inquiry. I made some progress, in fact. I got the GO_IF_LEGITIMATE_ADDRESS() macro to detect correctly REG+IMM addresses, and then the LEGITIMIZE_ADDRESS() macro to force them to be pre-computed in a register. However, now the compiler freaks out with an ICE.. :-/ I put some details below. Thanks for any clue that you or others can give me. Cheers, Sergio == This is a fragment of my LEGITIMIZE_ADDRESS(): - rtx legitimize_address(rtx X,rtx OLDX, enum machine_mode MODE) { rtx op1,op2,op,sum; op=NULL; ... if(GET_CODE(X)==PLUS && !no_new_pseudos) { op1=XEXP(X,0); op2=XEXP(X,1); if(GET_CODE(op1) == CONST_INT && (GET_CODE(op2) == REG || GET_CODE(op2) == SUBREG)) // base displacement { sum = gen_rtx_PLUS (MODE, op1, op2); op = force_reg(MODE, sum); } ... - Now when compiling a simple program such as: void foobar(int par1, int par2, int parN) { int a,b; a = 0x1234; b = a; } the instructions (n. 8,12,13) which compute the addresses in registers seem to be generated correctly: - ;; Function foobar ;; Register dispositions: 37 in 4 38 in 2 39 in 4 40 in 2 41 in 2 ;; Hard regs used: 2 4 30 (note 2 0 3 NOTE_INSN_DELETED) (note 3 2 6 0 NOTE_INSN_FUNCTION_BEG) ;; Start of basic block 1, registers live: 1 [A1] 29 [B13] 30 [B14] (note 6 3 8 1 [bb 1] NOTE_INSN_BASIC_BLOCK) (insn 8 6 9 1 (set (reg/f:HI 4 A4 [37]) (plus:HI (reg/f:HI 30 B14) (const_int -16 [0xfff0]))) 9 {addhi3} (nil) (nil)) (insn 9 8 10 1 (set (reg:HI 2 A2 [38]) (const_int 4660 [0x1234])) 5 {*constant_load} (nil) (nil)) (insn 10 9 12 1 (set (mem/i:HI (reg/f:HI 4 A4 [37]) [0 a+0 S2 A32]) (reg:HI 2 A2 [38])) 7 {*store_word} (nil) (nil)) (insn 12 10 13 1 (set (reg/f:HI 4 A4 [39]) (plus:HI (reg/f:HI 30 B14) (const_int -14 [0xfff2]))) 9 {addhi3} (nil) (nil)) (insn 13 12 14 1 (set (reg/f:HI 2 A2 [40]) (plus:HI (reg/f:HI 30 B14) (const_int -16 [0xfff0]))) 9 {addhi3} (nil) (nil)) (insn 14 13 15 1 (set (reg:HI 2 A2 [orig:41 a ] [41]) (mem/i:HI (reg/f:HI 2 A2 [40]) [0 a+0 S2 A32])) 4 {*load_word} (nil) (nil)) (insn 15 14 16 1 (set (mem/i:HI (reg/f:HI 4 A4 [39]) [0 b+0 S2 A16]) (reg:HI 2 A2 [orig:41 a ] [41])) 7 {*store_word} (nil) (nil)) ;; End of basic block 1, registers live: 1 [A1] 29 [B13] 30 [B14] (note 16 15 25 NOTE_INSN_FUNCTION_END) (note 25 16 0 NOTE_INSN_DELETED) - However, when I compile it $ hcc -da foobar8.c I get an ICE at the end of the compilation, and the assembly source is not produced: [ lots of my debugging output removed ] legitimate_address2(non-strict, soft-reg allowed), X= (reg/f:HI 29 B13) legitimate_address2() yes: (X)==REG && non_strict_base_reg(REGNO(X)) -MOVHI--- [generating a MOV X, Y insn] MOVHI: operands[0] (mem:HI (reg/f:HI 29 B13) [0 S2 A8]) MOVHI: operands[1] (reg:HI 31 B15) MOVHI --- END [then checking if -2(B13) is legitimate, it is not...] legitimate_address2(non-strict, soft-reg allowed), X= (plus:HI (reg/f:HI 29 B13) (const_int -2 [0xfffe])) legitimate_address2(): FOUND register+offset --> FAIL! legitimate_address2(non-strict, soft-reg allowed), X= (plus:HI (reg/f:HI 29 B13) (const_int -2 [0xfffe])) legitimate_address2(): FOUND register+offset --> FAIL! legitimate_address2(non-strict, soft-reg allowed), X= (plus:HI (reg/f:HI 29 B13) (const_int -2 [0xfffe])) legitimate_address2(): FOUND register+offset --> FAIL! legitimate_address2(non-strict, soft-reg allowed), X= (plus:HI (reg/f:HI 29 B13) (const_int -2 [0xfffe])) legitimate_address2(): FOUND register+offset --> FAIL! [and after four check of the add above, gcc 4.0.2 freaks out with ] foobar8.c: In function ‘foobar’: foobar8.c:7: internal compiler error: in change_address_1, at emit-rtl.c:1800 Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html> for instructions. The failed assertion is in line 1800: some "addr" is not an address. 1784 change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate) 1785 { 1786 rtx new; 1787 1788 gcc_assert (MEM_P (memref)); 1789 if (mode == VOIDmode) 1790 mode = GET_MODE (memref); 1791 if (addr == 0)
Re: porting GCC to a micro with a very limited addressing mode --- enforcing a 'register indirect memory operand' through a constraint in md
Thanks Micheal for your code, I will try it... however, I think the problem that crashes my compiler may not lie in my LEGITIMATE/LEGITIMIZE ADDRESS macros, which are equivalent to many others (yours included), but in the GCC which - in some corner cases - does not like being told that an register+offset is an invalid address. While investigating this hypothesis, I found this tutorial http://spindazzle.org/ggx/ which discusses a GCC port with the same constraints I am battling with, but solved in a different way. In this port, the register indirect addressing is enforced through a custom constraint in the MD (details below). What do you think of this approach? Sergio (from the patch to the MD) - ;; Constraints ;; - (define_constraint "W" "A register indirect memory operand." (and (match_code "mem") (match_test "REG_P (XEXP (op, 0)) && REGNO_OK_FOR_BASE_P (REGNO (XEXP (op, 0)))"))) which is then specified by the define_insn (define_insn "*movsi" [(set (match_operand:SI 0 "general_operand" "=r,r,W,m,r,r") (match_operand:SI 1 "ggx_general_movsrc_operand" "r,i,r,r,W,m"))] "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" "@ mov%0, %1 ldi.l %0, %1 st.l %0, %1 sta.l %0, %1 ld.l %0, %1 lda.l %0, %1") http://spindazzle.org/ggx/gcc/add-load-store.patch.txt The GO_IF_LEGITIMATE_ADDRESS() macro is plain and simple: /* A C compound statement with a conditional `goto LABEL;' executed if X (an RTX) is a legitimate memory address on the target machine for a memory operand of mode MODE. */ #define GO_IF_LEGITIMATE_ADDRESS(MODE,X,LABEL) \ do { \ if (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) \ goto LABEL; \ if (GET_CODE (X) == SYMBOL_REF \ || GET_CODE (X) == LABEL_REF\ || GET_CODE (X) == CONST) \ goto LABEL; \ } while (0) http://spindazzle.org/ggx/gcc/add-ggx-config.patch.txt Michael Hope wrote: > Hi Sergio. Here's the interesting parts from my port. The code's a > bit funny looking as I've edited it for this post. > > In .h: > > #define BASE_REG_CLASS ADDR_REGS > #define INDEX_REG_CLASS NO_REGS > > #ifdef REG_OK_STRICT > # define _REG_OK_STRICT 1 > #else > # define _REG_OK_STRICT 0 > #endif > > #define REGNO_OK_FOR_BASE_P(r) _regno_ok_for_base_p(r, > _REG_OK_STRICT) > #define REGNO_OK_FOR_INDEX_P(r) 0 > > In .c: > > static bool > _reg_ok(rtx reg, bool strict) > { > int regno = REGNO(reg); > > bool is_addr = _is_addr_regno(regno); > bool ok_strict = is_addr; > bool special = regno == ARG_POINTER_REGNUM > || regno == TREG_S > ; > > if (strict) > { > return ok_strict || special; > } > else > { > return ok_strict || special > || regno >= FIRST_PSEUDO_REGISTER > ; > } > } > > bool > _legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, >rtx x, >bool strict_checking) > { > /* (mem reg) */ > if (REG_P (x) > && _reg_ok (x, strict_checking) > ) > { > return 1; > } > > return 0; > } > > Note that this ISA only has indirect addressing and has no indirect + > offset or indirect + register modes. GCC > handles this just fine by splitting up any other type that fails > legitimate_address into smaller components. > > -- Michael > > On 10 February 2010 09:02, Sergio Ruocco wrote: >> Michael Hope wrote: >>> Hi Sergio. Any luck so far? >> Micheal, thanks for your inquiry. I made some progress, in fact. >> >> I got the GO_IF_LEGITIMATE_ADDRESS() macro to detect correctly REG+IMM >> addresses, and then the LEGITIMIZE_ADDRESS() macro to force them to be >> pre-computed in a register. >> >> However, now the compiler freaks out with an ICE.. :-/ I put some >> details below. Thanks for any clue that you or others can give me. >> >> Cheers, >> >>Sergio >> >> == >> >> >> This is a fragment of my LEGITIMIZE_ADDRESS(): >> -
Re: porting GCC to a micro with a very limited addressing mode --- enforcing a 'register indirect memory operand' through a constraint in md
I found the source of my problems! The prologue()/epilogue() functions (*) I took from the tutorial written for SPIM/MIPS emit a number of move insn to/from "invalid" memory addresses (reg+off) that do not go through LEGITIMIZE_ADDRESS(), and this freaks out GCC, so I have to rewrite these in some ways... It seems that prologue()/epilogue() are called quite late in the compiling process, thus new registers cannot be created (no_new_pseudos assert fires) and/or emit_move_insn() does not go through LEGITIMIZE_ADDRESS()... will work on this tomorrow... Thanks for the support so far! Sergio (*) void spim_prologue(void) { int i,j; emit_move_insn(gen_rtx_MEM(HImode,plus_constant(stack_pointer_rtx,0)),return_addr_rtx); emit_move_insn(gen_rtx_MEM(HImode,plus_constant(stack_pointer_rtx,-2)),stack_pointer_rtx); emit_move_insn(gen_rtx_MEM(HImode,plus_constant(stack_pointer_rtx,-4)),hard_frame_pointer_rtx); ... } Sergio Ruocco wrote: > > Thanks Micheal for your code, I will try it... however, I think the > problem that crashes my compiler may not lie in my LEGITIMATE/LEGITIMIZE > ADDRESS macros, which are equivalent to many others (yours included), > but in the GCC which - in some corner cases - does not like being told > that an register+offset is an invalid address. > > While investigating this hypothesis, I found this tutorial > > http://spindazzle.org/ggx/ > > which discusses a GCC port with the same constraints I am battling with, > but solved in a different way. > > In this port, the register indirect addressing is enforced through a > custom constraint in the MD (details below). > > What do you think of this approach? > > Sergio > > (from the patch to the MD) > > - > ;; Constraints > ;; - > (define_constraint "W" > "A register indirect memory operand." > (and (match_code "mem") >(match_test "REG_P (XEXP (op, 0)) > && REGNO_OK_FOR_BASE_P (REGNO (XEXP (op, 0)))"))) > > > which is then specified by the define_insn > > (define_insn "*movsi" >[(set (match_operand:SI 0 "general_operand" "=r,r,W,m,r,r") > (match_operand:SI 1 "ggx_general_movsrc_operand" "r,i,r,r,W,m"))] >"register_operand (operands[0], SImode) > || register_operand (operands[1], SImode)" >"@ > mov%0, %1 > ldi.l %0, %1 > st.l %0, %1 > sta.l %0, %1 > ld.l %0, %1 > lda.l %0, %1") > > http://spindazzle.org/ggx/gcc/add-load-store.patch.txt > > > The GO_IF_LEGITIMATE_ADDRESS() macro is plain and simple: > > /* A C compound statement with a conditional `goto LABEL;' executed >if X (an RTX) is a legitimate memory address on the target machine >for a memory operand of mode MODE. */ > #define GO_IF_LEGITIMATE_ADDRESS(MODE,X,LABEL)\ > do { \ > if (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) \ > goto LABEL; \ > if (GET_CODE (X) == SYMBOL_REF\ > || GET_CODE (X) == LABEL_REF\ > || GET_CODE (X) == CONST) \ > goto LABEL; \ > } while (0) > > http://spindazzle.org/ggx/gcc/add-ggx-config.patch.txt > > > > > Michael Hope wrote: >> Hi Sergio. Here's the interesting parts from my port. The code's a >> bit funny looking as I've edited it for this post. >> >> In .h: >> >> #define BASE_REG_CLASS ADDR_REGS >> #define INDEX_REG_CLASS NO_REGS >> >> #ifdef REG_OK_STRICT >> # define _REG_OK_STRICT 1 >> #else >> # define _REG_OK_STRICT 0 >> #endif >> >> #define REGNO_OK_FOR_BASE_P(r) _regno_ok_for_base_p(r, >> _REG_OK_STRICT) >> #define REGNO_OK_FOR_INDEX_P(r) 0 >> >> In .c: >> >> static bool >> _reg_ok(rtx reg, bool strict) >> { >> int regno = REGNO(reg); >> >> bool is_addr = _is_addr_regno(regno); >> bool ok_strict = is_addr; >> bool special = regno == ARG_POINTER_REGNUM >> || regno == TREG_S >> ; >> >> if (strict) >> { >> return ok_strict || special; >> } >> else >> { >> return ok_strict || special >> || regno >= FIRST_PSEUDO_REGISTER >> ; >> } >> } >> >&g
Re: GCC porting tutorials
Hi Radu, Check both the GCC Wiki and the work done at IIT Bombay: http://www.cse.iitb.ac.in/grc/reach.html Activities->Workshops They developed some tutorials on porting GCC and writing new backends, such as: http://www.cse.iitb.ac.in/grc/gcc-workshop-09/ http://www.cse.iitb.ac.in/~uday/gcc-mini-workshop/ On 24 April 2010 10:53, Radu Hobincu wrote: > Hello, > > My name is Radu Hobincu, I am part of a team at "Politehnica" University > of Bucharest that is developing a massive parallel computing architecture > and currently my job is to port the GCC compiler to this new machine. > > I've been looking over the GCC official site at http://gcc.gnu.org/ but I > couldn't find an official porting tutorial. Is there such a thing? And > maybe a small example for a lightweight architecture? > > Regards, > Radu >
Trouble with MDs: "const" RTL object stops recognition of RTL expressions by insn patterns
Dear All, I am porting GCC to a 16 bit micro (with 16 bit bytes, thus BITS_PER_UNIT=16, 16 bit ints become "QI"s etc). The port compiles is nearly done and simple C programs, but now chokes on a trivial line such as: yyy(&array[4], &e, &p); with this error: xxx.c: In function ‘yyy’: xxx.c:193: error: unrecognizable insn: (insn 183 181 184 4 (set (reg/f:QI 37 [ D.1127 ]) (const:QI (plus:QI (symbol_ref:QI ("digest") [flags 0x2] ) (const_int 8 [0x8] -1 (nil) (nil)) sha1_16_struct2.c:193: internal compiler error: in extract_insn, at recog.c:2020 Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html> for instructions. I determined that the problem is triggered by the computation of array address+const (4/8 in this case). My MD contains: (define_insn "addqi3" [(set (match_operand:QI 0 "register_operand" "=r,r") (plus:QI (match_operand:QI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "r,K")) )] "" "@ ADD \\t%2 %0 ADDI \\t%h2 %0" ) which correctly compiles ordinary arithmetic expressions: x = 5+y etc. However, when a symbol is involved, the addqi3 isns pattern cannot recognise the RTL: Symbol+Int. Is maybe the surrounding (const:QI...) the reason why addqi3 does not match?! Grepping the GCC source I found in rtl.h that CONST is defined as: /* This is used to encapsulate an expression whose value is constant (such as the sum of a SYMBOL_REF and a CONST_INT) so that it will be recognized as a constant operand rather than by arithmetic instructions. */ DEF_RTL_EXPR(CONST, "const", "e", RTX_CONST_OBJ) So, what is my port missing to make it compile such RTL expressions? I feel that it must be something really trivial which I am overlooking.. Thanks for your help, Sergio
Re: [AD] UltraGDB, an alternative tool to debug GCC, GDB, LLDB, etc. on Windows and Linux
On Tuesday, July 07 2015, Chiheng Xu wrote: > UltraGDB is a GDB GUI front-end, as well as a lightweight C/C++ IDE > based on industry standard Eclipse technology. > > Visit http://www.ultragdb.com/ to learn more. > > Visit https://www.youtube.com/channel/UCr7F3ZZ_hgpxYXiMOA27hhw for demos. Hello Chiheng, I tried to find the source code of this package, but I could not find it. Do you have a URL or something you can provide? Thank you, -- Sergio GPG key ID: 237A 54B1 0287 28BF 00EF 31F4 D0EB 7628 65FC 5E36 Please send encrypted e-mail if possible http://sergiodj.net/
Re: [AD] UltraGDB, an alternative tool to debug GCC, GDB, LLDB, etc. on Windows and Linux
On Tuesday, July 07 2015, Chiheng Xu wrote: >> I tried to find the source code of this package, but I could not find >> it. Do you have a URL or something you can provide? >> > Sorry, source code of UltraGDB is not available now. The source code > is actually a trimmed down, supercharged, and re-branded Eclipse CDT. > All of our technology is built on open source, and for open source. It > maybe weird for us not to provide the source code. But we are just > founded, we have no idea how to continue developing this product. In > other word, we have no business model yet. At present, we just want > to know whether or not our product is useful, if so, then we think it > is meaningful to work on it. > > This product is actually a part of much bigger and more ambitious plan > that can't be disclosed right now. In the future, we may decide to > provide the source code of UltraGDB. > > Any comment or suggestion on the UltraGDB product, or "development > model", or "business model" is welcomed. [ Removing lldb-dev from the Cc list as requested. ] Hi, First of all, you are repackaging Eclipse CDT and are not distributing the source code for it; in fact, you have relicensed the entire project with a proprietary license. Eclipse CDT is license under EPL: <https://www.eclipse.org/org/documents/epl-v10.php> Which forbids this practice. EPL still allows you to license your plugin as proprietary, but you still have to release the source code of everything else (and if you modified Eclipse CDT in some way, you also have to release your modifications). Secondly, what is the advantage of UltraGDB when you compare it with the Eclipse CDT Standalone Debugger? <https://wiki.eclipse.org/CDT/StandaloneDebugger> The Standalone Debugger is Free Software (released under the EPL as well), and distributed along with the Eclipse CDT on some distributions (Fedora GNU/Linux, for example). It is nice to see people developing other plugins and GUI's for GDB (assuming they are Free Software as well, of course), but it looks to me that Standalone Debugger offers a better user experience than UltraGDB. Thank you, -- Sergio GPG key ID: 237A 54B1 0287 28BF 00EF 31F4 D0EB 7628 65FC 5E36 Please send encrypted e-mail if possible http://sergiodj.net/
Pointer to the current function
Hello: I wonder what do you think about a patch to implement getting a pointer to the current function. Is it a "no, under no circumstances"? Or it is a "maybe, show us the code"? I'll explain better what I mean: currently there is the statement __func__ that returns a string with the name of the current function. This allows to print (for example from a macro) which is the current function name. Along with __LINE__ it is useful for debugging, among other things. But I miss an statement that allows to have a pointer to the current function. Thus putting it in a macro would allow to have a pointer to the function where that macro is. It would be very useful for coroutines, for example. I've been searching and can't find a simple way of doing it. Some people proposes to use __func__ combined with dlsym and dlopen, but it is slow and clearly a hack, and forces to use -rdynamic, which is not always possible/desirable. Currently I use another macro to define the function itself, passing the desired name as an argument and creating a variable with a pointer to it, but it is ugly. Thanks. -- Nos leemos RASTER(Linux user #228804) rasters...@gmail.comhttps://www.rastersoft.com
Re: Updated Sourceware infrastructure plans
On Wednesday, May 01 2024, Mark Wielaard wrote: [...] > But the part that interests me most is the self-registration part that > Sergio setup. I believe we will need that for whatever system we end > up with to make it as easy to contribute as it is with email. > https://blog.sergiodj.net/posts/installing-gerrit-and-keycloak/ [...] Hey Mark, If I were to set this up today, I would look at Authentik (which is what I'm using for my personal services). It is a bit simpler than Keycloak. I would also certainly go for a container deployment of the service instead, because (as you can see in the blog post) it's not trivial to set things up in a correct manner. Let me know if you need help with this! Thanks, -- Sergio GPG key ID: 237A 54B1 0287 28BF 00EF 31F4 D0EB 7628 65FC 5E36 Please send encrypted e-mail if possible https://sergiodj.net/