<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://sdcc.sourceforge.net/mediawiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://sdcc.sourceforge.net/mediawiki/index.php?title=Random_notes_about_sdcc_and_how_it_works&amp;feed=atom&amp;action=history</id>
		<title>Random notes about sdcc and how it works - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://sdcc.sourceforge.net/mediawiki/index.php?title=Random_notes_about_sdcc_and_how_it_works&amp;feed=atom&amp;action=history"/>
		<link rel="alternate" type="text/html" href="http://sdcc.sourceforge.net/mediawiki/index.php?title=Random_notes_about_sdcc_and_how_it_works&amp;action=history"/>
		<updated>2013-05-25T18:28:03Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.20.2</generator>

	<entry>
		<id>http://sdcc.sourceforge.net/mediawiki/index.php?title=Random_notes_about_sdcc_and_how_it_works&amp;diff=34&amp;oldid=prev</id>
		<title>Borutr: Created page with &quot;&lt;pre&gt; Random notes ------------ A random set of notes about sdcc and how it works.  Michael on the register allocation stage: ----------------------------------------- Lets tr...&quot;</title>
		<link rel="alternate" type="text/html" href="http://sdcc.sourceforge.net/mediawiki/index.php?title=Random_notes_about_sdcc_and_how_it_works&amp;diff=34&amp;oldid=prev"/>
				<updated>2012-12-04T10:59:47Z</updated>
		
		<summary type="html">&lt;p&gt;Created page with &amp;quot;&amp;lt;pre&amp;gt; Random notes ------------ A random set of notes about sdcc and how it works.  Michael on the register allocation stage: ----------------------------------------- Lets tr...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
Random notes&lt;br /&gt;
------------&lt;br /&gt;
A random set of notes about sdcc and how it works.&lt;br /&gt;
&lt;br /&gt;
Michael on the register allocation stage:&lt;br /&gt;
-----------------------------------------&lt;br /&gt;
Lets trace how the register allocator in the mcs51 port works.&lt;br /&gt;
&lt;br /&gt;
Some concepts:&lt;br /&gt;
eBBlock&lt;br /&gt;
        A basic block.  I can't remember the conditions, but a basic block&lt;br /&gt;
is one that is easy to optimise and analyse.  I guess this means that it has&lt;br /&gt;
a nice set of assignments and a reasonably straight flow.&lt;br /&gt;
iCode&lt;br /&gt;
        Intermediate code.  Provides the interface between the parser + optimiser&lt;br /&gt;
and the code generator by providing an abstract machine with infinite registers&lt;br /&gt;
which the parser can generate for and the back end can turn into real code.&lt;br /&gt;
iTemps&lt;br /&gt;
        An iTemp is a temporary register used in iCode.  These will eventually&lt;br /&gt;
be either replaced, allocated into a register, or placed onto the stack by the&lt;br /&gt;
backend.&lt;br /&gt;
Live range&lt;br /&gt;
     The live range of an iTemp is the part of the code that the iTemp is used&lt;br /&gt;
over.  Generally the live range of an iTemp is from its first assignment to its&lt;br /&gt;
last use.&lt;br /&gt;
&lt;br /&gt;
Input to mcs51_assignRegisters is an array of basic blocks.  Assign&lt;br /&gt;
registers is normally called at the end of a function.&lt;br /&gt;
&lt;br /&gt;
In pseudo code,&lt;br /&gt;
1.  For each basic block, pack the registers in the block.&lt;br /&gt;
    In this case register packing consists of:&lt;br /&gt;
       Remove any unneded iTemps that are just used in assignments.&lt;br /&gt;
       Mark anything that can be rematerialised as rematerialisable.&lt;br /&gt;
           There is no way I spelt that correctly.  Something is rematerialisable&lt;br /&gt;
           if it can be generated easily and is constant, and hence dosn't need&lt;br /&gt;
           to be cached away in an iTemp.  An example is the address of something.&lt;br /&gt;
       Packs iTemps that are only used once into normally unavailable registers.&lt;br /&gt;
    Register packing removes unneeded iTemps.&lt;br /&gt;
2.  Determine what number and type of registers are needed for each&lt;br /&gt;
    live range.&lt;br /&gt;
    It does&lt;br /&gt;
       If the iTemp lives for zero time, don't bother assigning&lt;br /&gt;
       If its not an iTemp, skip for now.&lt;br /&gt;
       If its a conditional (determined in the register packing), skip as it will&lt;br /&gt;
       be stored in carry.&lt;br /&gt;
       If the iTemp is already packed from 1.c, skip&lt;br /&gt;
       If the iTemp is remat and some other magic, skip.&lt;br /&gt;
       Else set the number and type of registers based on the size of the iTemp.&lt;br /&gt;
3.  Assign registers for each segment.&lt;br /&gt;
    For each iCode, do&lt;br /&gt;
        If it is a IPOP (pop of an iTemp at the end of a block), reset the LR.&lt;br /&gt;
        De-assign the live ranges of the iTemps that expire here.&lt;br /&gt;
            For each iTemp, do&lt;br /&gt;
                If this iTemp is still alive, skip&lt;br /&gt;
                If this iTemp is spilt on the stack, free the location and continue.&lt;br /&gt;
                If there are no registers assigned (?), continue.&lt;br /&gt;
                Some magic using IFX and IPOP&lt;br /&gt;
                If the iTemp has no registers, continue.&lt;br /&gt;
                If the result of this iCode doesnt yet have registers, allocate them now.  Weird.&lt;br /&gt;
                Deallocate the registers used.&lt;br /&gt;
        Skip instructions that dont need registers (IFX, JUMPTABLE, POINTER_SET)&lt;br /&gt;
        Only assign registers to the result of this iCode.&lt;br /&gt;
        If the iCode has registers, or has been spilt, continue.&lt;br /&gt;
        If this will cause a spill as it needs more registers than are free, then&lt;br /&gt;
            Find those that can be spilt.&lt;br /&gt;
            Spill this if its easy.&lt;br /&gt;
            Spill this if its the least used.&lt;br /&gt;
        Allocate registers to the result iTemp     &lt;br /&gt;
        If any registers in the result are shared with the operand, make them line up.&lt;br /&gt;
4.  Create the register mask for each segment.&lt;br /&gt;
    For each iCode, do&lt;br /&gt;
        Set the used register bit vector from the used registers.&lt;br /&gt;
        Mark these registers as used in the higher function.  This lets the generator&lt;br /&gt;
        decide which registers need to be saved when calling or being called by a function.&lt;br /&gt;
        Hmm.  It seems to re-setup the used register bit vector.&lt;br /&gt;
5.  Redo the stack offsets.&lt;br /&gt;
6.  Turn the basic blocks into an intermediate code chain.&lt;br /&gt;
        Takes the array of basic blocks and pulls them out into one iCode chain.&lt;br /&gt;
7.  Optimise the labels in the iCode chain.&lt;br /&gt;
        Skipped if the label optimisations are turned off.&lt;br /&gt;
        Remove any gotos that go to the next line.&lt;br /&gt;
        Simplify any chained gotos&lt;br /&gt;
        Remove unreferenced labels&lt;br /&gt;
        Remove unreferenced code.&lt;br /&gt;
7.  Generate the mcs51 code from the iCode chain.&lt;br /&gt;
8.  Deallocate everything (registers and stack locations).&lt;br /&gt;
&lt;br /&gt;
Sandeep:&lt;br /&gt;
--------&lt;br /&gt;
=======&lt;br /&gt;
Sandeep:&lt;br /&gt;
--------&lt;br /&gt;
The Register Allocation story.&lt;br /&gt;
&lt;br /&gt;
Before I get into this there are a few important fields&lt;br /&gt;
on the iCode &amp;amp; oprtand data structures that need to be&lt;br /&gt;
addressed.&lt;br /&gt;
&lt;br /&gt;
iCode.&lt;br /&gt;
-----&lt;br /&gt;
        -&amp;gt;key  -  is an unique number assigned to this&lt;br /&gt;
                  iCode when this icode is allocated.&lt;br /&gt;
&lt;br /&gt;
        -&amp;gt;seq  - sequence number of the iCode given in&lt;br /&gt;
                 ascending order of execution.&lt;br /&gt;
&lt;br /&gt;
operand.&lt;br /&gt;
-------&lt;br /&gt;
        -&amp;gt;key  - unique number for an operand when operand&lt;br /&gt;
                 is allocated.&lt;br /&gt;
&lt;br /&gt;
OP_LIVEFROM(op) - sequence number of the iCode where it was&lt;br /&gt;
                  first defined. Computed in SDCClrange.c&lt;br /&gt;
&lt;br /&gt;
OP_LIVETO(op)   - sequence number of the iCode where it is&lt;br /&gt;
                  last used. Computed in SDCClrange.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                 &lt;br /&gt;
&lt;br /&gt;
Sandeep:&lt;br /&gt;
--------&lt;br /&gt;
Adding memory maps for AVR, setup default map for&lt;br /&gt;
local &amp;amp; global variables in port.h will be initialised&lt;br /&gt;
by the _&amp;lt;port&amp;gt;_finaliseOptions() [good functions]..some&lt;br /&gt;
kludges remain because of the &amp;quot;overlay&amp;quot; segment for 8051.&lt;br /&gt;
&lt;br /&gt;
The memory segment stuff will have to be made more flexible.&lt;br /&gt;
Currently there does not seem to be a 1-to-1 correspondence &lt;br /&gt;
between storage class &amp;amp; memory map. (should there be??).&lt;br /&gt;
&lt;br /&gt;
Also Added check for memory map in SDCCmem.c allocLocal&lt;br /&gt;
and allocglobal for &amp;quot;eeprom&amp;quot; memory space (AVR).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Michael:&lt;br /&gt;
--------&lt;br /&gt;
Tracing parmBytes and function calls.&lt;br /&gt;
&lt;br /&gt;
Bug:&lt;br /&gt;
void printf(const char *format);&lt;br /&gt;
&lt;br /&gt;
void puts(const char *s)&lt;br /&gt;
{&lt;br /&gt;
        printf(s);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Generates the pseudo-code:&lt;br /&gt;
          hl = s&lt;br /&gt;
          push hl&lt;br /&gt;
          call printf&lt;br /&gt;
          pop l (not hl - so parmBytes is too small)&lt;br /&gt;
&lt;br /&gt;
parmBytes for a function call seems to be setup in geniCodeCall in&lt;br /&gt;
SDCCicode.c.&lt;br /&gt;
&lt;br /&gt;
geniCodeCall:&lt;br /&gt;
* Takes care of calls with side effects (?)&lt;br /&gt;
* Generates the icode to push the parameters (this also computes the &lt;br /&gt;
  resulting stack size)&lt;br /&gt;
* Generates a CALL or PCALL depending on if its a function or pointer to.&lt;br /&gt;
* Computes the result&lt;br /&gt;
* Adds the code for the call to the chain.&lt;br /&gt;
&lt;br /&gt;
My bug is probably in geniCodeParms - it's probably computing the&lt;br /&gt;
size of pointers wrong.&lt;br /&gt;
&lt;br /&gt;
geniCodeParms:&lt;br /&gt;
* A 'parm' node causes this to be run on the tree branches.&lt;br /&gt;
* It switches on the stack mode and sendto mode, and adds the&lt;br /&gt;
  instructions required to push or put.&lt;br /&gt;
* A push adds the result of 'getSize' to the stack size.&lt;br /&gt;
&lt;br /&gt;
So the bug is probably in getSize.  's' is not an aggregate, so the&lt;br /&gt;
bug is in getSize().&lt;br /&gt;
&lt;br /&gt;
It seems that IS_SPEC() is being set, deferencing *s so that it's size&lt;br /&gt;
is sizeof(char) == 1.  It's either a SPECIFIER or a DECLARATOR - seems that&lt;br /&gt;
were the wrong way around.  This is set in SDCCsymt.c, SDCCval.c, and the &lt;br /&gt;
yacc file. SDCCsymt.c and SDCCval.c havnt really changed in 5 days - must&lt;br /&gt;
be SDCC.y.  Nope, no changes.  diff against 5 days ago shows only interesting&lt;br /&gt;
changes are in SDCCicode.  Same with -14 days.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Borutr</name></author>	</entry>

	</feed>