Forum: Compiler & IDEs SDCC 3.6.0 RC1


von Philipp Klaus K. (pkk)


Lesenswert?

Demnächst wird SDCC 3.6.0 erscheinen. Es gibt nun einen RC1 (siehe auch 
NEWS unter http://sdcc.sourceforge.net/). Das ist somit die letzte 
Gelegenheit, noch Bugs in der aktuellen Version zu finden, bevor 3.6.0 
erscheint. Besonders schwerwiegende oder einfach zu behebende Bugs 
könntne dann noch rechtzeitig vor 3.6.0 behoben werden.

Philipp

P.S.: Von SDCC gibt es üblicherweise ein Release pro Jahr, das dann auch 
in Distributionen wie Debian eingeht.

von Jens (Gast)


Lesenswert?

Welche neuen Features darf man denn bei 3.6 erwarten?
Bei welchen Architekturen hat sich was getan?
Irgendwie habe ich das ChangeLog nicht gefunden...

Jens

von Philipp Klaus K. (pkk)


Lesenswert?

Jens schrieb:
> Welche neuen Features darf man denn bei 3.6 erwarten?
> Bei welchen Architekturen hat sich was getan?
> Irgendwie habe ich das ChangeLog nicht gefunden...
>
> Jens

Das volle Changelog gibe es in den Quellen:
https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc/ChangeLog
Aber das ist halt sehr lang, weil da jeder kleine Bugfix auftaucht.
Eine Übersicht der wichtigsten Änderungen seit 3.5.0 findet sich unten 
auf http://sdcc.sourceforge.net/mediawiki/index.php/SDCC_3.6.0_Release

Philipp

von Jens (Gast)


Lesenswert?

Vielen Dank für Eure Arbeit!

Philipp Klaus K. schrieb:
> Das volle Changelog gibe es in den Quellen:
> https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc/ChangeLog
> Aber das ist halt sehr lang, weil da jeder kleine Bugfix auftaucht.
Dafür kann man ganz gut drin suchen.

Jens

von Joerg W. (joergwolfram)


Lesenswert?

Ich hab jetzt ein Problem (CC2541->MCS51) beim SDCC 3.6.0 festgestellt, 
welches beim 3.5.0 nicht vorhanden war. Aus
1
while(SEMAPHORE_0==0){};

entsteht im Listing:
1
    00003E                       1144 00101$:
2
    00003E 90 61 8A         [24] 1145   mov  dptr,#_SEMAPHORE_0
3
    000041 E0               [24] 1146   movx  a,@dptr
4
    000042 E0               [24] 1147   movx  a,@dptr
5
    000043 60 F9            [24] 1148   jz  00101$

Da bei MOVX kein Flag gesetzt wird, kann das Ganze m.E. nicht richtig 
funktionieren.

Jörg

von TomA (Gast)


Lesenswert?

Hallo Jörg,

soweit ich mich erinnere hat MCS51 kein Zero-Flag. Zum JZ-Sprung wird 
der momentane Inhalt des Accu geprüft. Soweit wäre das schon in Ordnung. 
Aber warum wird die Speicherzelle zwei mal gelesen? Auch wenn deine 
Variable 16Bit breit ist, macht das so keinen Sinn.

Gruß. Tom

von Joerg W. (joergwolfram)


Lesenswert?

Stimmt, das ist mir in dem Moment nicht eingefallen. Das Problem scheint 
wohl eine andere Ursache zu haben und hier muss ich erst mal ein 
Testprogramm schreiben. Denn derzeit werden fast alle Unterfunktionen 
durch eine Bibliothek bereitgestellt und nur dazugelinkt.

Momentan bin ich wieder auf 3.5.0 zurück gewechselt, da habe ich das 
Problem nicht.

Jörg

von Philipp Klaus K. (pkk)


Lesenswert?

Joerg W. schrieb:
> Das Problem scheint
> wohl eine andere Ursache zu haben

Weißt Du schon genaueres?

Philipp

von Joerg W. (joergwolfram)


Lesenswert?

Ich hatte es inzwischen ein bisschen aus den Augen verloren, aber heute 
früh kam mir dann die "Erleuchtung". Ich hab dazu ein kleines 
Testprogramm geschrieben. Und es liegt doch an dem doppelten "movx 
a,@dptr".
1
                                   1189 ;  src/main.c:18: while(SEMAPHORE_0 == 0);
2
      00005F                       1190 00101$:
3
      00005F 90 61 8A         [24] 1191   mov  dptr,#_SEMAPHORE_0
4
      000062 E0               [24] 1192   movx  a,@dptr
5
      000063 E0               [24] 1193   movx  a,@dptr
6
      000064 60 F9            [24] 1194   jz  00101$


Die Semaphoren gehen nach "0", wenn man sie bei "1" liest, Durch das 
doppelte Lesen geht aber die "1" vom ersten Lesen verloren und 
"while(SEMAPHORE_0 == 0);" landet immer in einer Endlosschleife. Der 
SDCC3.5.0 macht an der Stelle:
1
                                   1190 ;  src/main.c:18: while(SEMAPHORE_0 == 0);
2
      00005F                       1191 00101$:
3
      00005F 90 61 8A         [24] 1192   mov  dptr,#_SEMAPHORE_0
4
      000062 E0               [24] 1193   movx  a,@dptr
5
      000063 FF               [12] 1194   mov  r7,a
6
      000064 60 F9            [24] 1195   jz  00101$

Hier wird nur einmal gelesen was ja OK ist.

Bei anderen Registern macht das doppelte Lesen nichts aus, bei den 
Semaphoren aber schon.

Jörg

: Bearbeitet durch User
von Philipp Klaus K. (pkk)


Lesenswert?

Wie ist SEMAPHORE_0 deklariert?
Hättest Du noch ein kompilierbares Minimalbeispiel, bei dem das Problem 
sichtbar ist?

Philipp

von Joerg W. (joergwolfram)


Angehängte Dateien:

Lesenswert?

SEMAPHORE_0 ist als __xdata volatile unsigned char deklariert. Anbei das 
Beispiel, das Makefile muss halt noch an die richtige Toolchain 
angepasst werden. Die while-Schleife steht bei mir normalerweise am 
Anfang der Radio-Initialisierung.


Jörg

von Philipp Klaus K. (pkk)


Lesenswert?

Mit SDCC 3.6.0 konnte ich das Problem reproduzieren.
Ich meine mich erinnern, das so etwas ähnliches vor ein paar Monaten 
schon 'mal irgendwo (eine der SDCC-Mailinglisten?) auftauchte, und 
behoben wurde.
In aktuellen Entwicklerversionen (3.6.4 #9802 und 3.6.4 #9811 die ich 
eh' gerade da hatte), ist der generierte Code zwar auch nicht unbedingt 
schön, aber immerhin korrekt.
Damit wird das Problem wohl auch in SDCC 3.7.0 nicht wieder auftauchen.

Philipp

von Christian J. (Gast)


Lesenswert?

Hi,

sag mll Philipp, wieso habt ihr die Datentypen bei putchar und getchar 
jetzt auf int gesetzt? Ich musste da etliche Fehlermeldung bei meinem 
Z80 Oldie-Dampf-Board ausbügeln, weil ich die beiden Funktionen 
überschrieben habe, um eine RS232 Ausgabe auf ein Terminal zu erzeugen.

Tat das Not?

es ist halt ärgerlich wenn bei jeder neuen Version immer wieder neue 
Komplierfehler auftauchen, die vorher nicht da waren.

gruss,
Christian

von Nop (Gast)


Lesenswert?

Christian J. schrieb:

> sag mll Philipp, wieso habt ihr die Datentypen bei putchar und getchar
> jetzt auf int gesetzt?

Vermutlich, weil das mit der C-Standardlibrary dann auch übereinstimmt. 
Die hat dort deswegen int und nicht char, weil man dann auch Sachen wie 
EOF oder sonstige Fehler zurückbekommen kann. Mit char ginge das nicht, 
weil alle Werte von 0-255 ja gültige Datenwerte sind.

von Philipp Klaus K. (pkk)


Lesenswert?

Nop schrieb:
> Christian J. schrieb:
>
>> sag mll Philipp, wieso habt ihr die Datentypen bei putchar und getchar
>> jetzt auf int gesetzt?
>
> Vermutlich, weil das mit der C-Standardlibrary dann auch übereinstimmt.
> Die hat dort deswegen int und nicht char, weil man dann auch Sachen wie
> EOF oder sonstige Fehler zurückbekommen kann. Mit char ginge das nicht,
> weil alle Werte von 0-255 ja gültige Datenwerte sind.

So ist es. Oder wie ich für die Release Notes geschrieben habe: "Changed 
putchar() prototype from void putchar(char) to int putchar(int) to 
improve standard-compliance and allow error reporting." 
(http://sdcc.sourceforge.net/mediawiki/index.php/SDCC_3.7.0_Release).

> es ist halt ärgerlich wenn bei jeder neuen Version immer wieder neue
> Komplierfehler auftauchen, die vorher nicht da waren.

> gruss,
> Christian

Die alte Situation, in der die Kompilierfehler bei standardkonformem 
Code auftraten war aber noch unschöner.

Philipp

von Christian J. (Gast)


Lesenswert?

Philiiiiiiip........

habt ihr schon wieder am sdcc rumgespielt? Naa...... ?

Aslink Warning-Undefined Global ::sdcc_heap_init referened by module 
crt0

Lief vorher, jetzt nicht mehr.... weder mit 1  noch mit 2 _ ich 
brauche den Heap aber unbedingt. Wenigstens 512 Bytes. Bin wieder im Z80 
Fieber diese 2014 zusammen gefrickelte Kiste zum Leben zu bringen.
1
;--------------------------------------------------------------------------
2
; crt0.s - Generic crt0.s for a Z80
3
;
4
; Minimum Z80 System mit Mostek 3801 Multi I/O Chip
5
;
6
;  1. Leeres RAM nullen
7
;  2. Evtl direkt ins Userprogramm rein
8
;  3. Interrupt Tabelle (32 Bytes) nach $4040 kopieren
9
;  4. Mode 2 einschalten Register und MK3801 (IM2)
10
;  5. I Register auf RAM Tabelle legen
11
;  6. Keine Ints zulassen
12
;--------------------------------------------------------------------------
13
14
    .module crt0            ; Modul Name für den Linker
15
16
    ; Memory Map Adressen der Zeropage (vom Benutzer definierbar)
17
    ; Definitions
18
19
    offset           .equ   0x0000   ; Basisadresse des Codes
20
    reset_vector     .equ   offset
21
    stack            .equ   0x0000   ; Stack
22
    adr_vec_table    .equ   0x40     ; Mode 2 Vektor Tabelle für STI Mostek Multi I/O
23
    adr_nmi          .equ   0x66     ; NMI Reset Vektor
24
    adr_copyright    .equ   0x80
25
    ram_prog         .equ   0x4000   ; Beginn des Userprogrammes im RAM
26
    heap_size        .equ   512      ; Benutzer definierte Heap Groesse
27
28
    ; Globale Funktionen und Variablen für das C-Programm
29
30
    .globl  _main
31
    .globl  _nmi_vint       ; Funktion des NMI Handlers
32
    .globl __sdcc_heap_init
33
    .globl _vector_table
34
35
    ; Interruptroutinen für den Mostek MK3801 Multi I/O Baustein
36
    ; Manual STI Baustein MK3801 Figure 7
37
    .globl  _vector_table
38
    .globl  _int_sti_gpi_0  ; General Purpose Interrupt 0
39
    .globl  _int_sti_gpi_1  ; General Purpose Interrupt 1
40
    .globl  _int_sti_gpi_2  ; General Purpose Interrupt 2
41
    .globl  _int_sti_gpi_3  ; General Purpose Interrupt 3
42
    .globl  _int_sti_timer_d
43
    .globl  _int_sti_timer_c
44
    .globl  _int_sti_gpi_4  ; General Purpose Interrupt 4
45
    .globl  _int_sti_gpi_5  ; General Purpose Interrupt 5
46
    .globl  _int_sti_timer_b
47
    .globl  _int_sti_transmit_error
48
    .globl  _int_sti_transmit_buffer_empty
49
    .globl  _int_sti_receive_error
50
    .globl  _int_sti_receive_buffer_full
51
    .globl  _int_sti_timer_a
52
    .globl  _int_sti_gpi_6  ; General Purpose Interrupt 6
53
    .globl  _int_sti_gpi_7  ; General Purpose Interrupt 7
54
55
    .globl l__INITIALIZER
56
    .globl s__INITIALIZER
57
    .globl s__INITIALIZED
58
59
    ; -------------------------------------------------------------
60
61
    .area   _HEADER (ABS)
62
63
    ; Reset vector bei Kaltstart und Sprung ins User Programm
64
    .org    reset_vector
65
     jp init
66
67
68
    ; Tabelle der RST Vektoren für Software Interrupts auf RAM umlegen
69
     .org 0x08
70
     jp ram_prog+0x0008
71
     .org 0x10
72
     jp ram_prog+0x0010
73
     .org 0x18
74
     jp ram_prog+0x0018
75
     .org 0x20
76
     jp ram_prog+0x0020
77
     .org 0x28
78
     jp ram_prog+0x0028
79
     .org 0x30
80
     jp ram_prog+0x0030
81
     .org 0x38
82
     jp ram_prog+0x0038
83
84
    ;///////////////////////////////////////////////////////////
85
    ; Tabelle der Mode 2 Int Vektoren auf die Handler Funktionen im C Modul
86
    ; Reihenfolge beachten !!! Siehe Manual Mostek 3801, Interrupt Tabelle
87
88
    .org adr_vec_table
89
    _vector_table:
90
    .dw (_int_sti_gpi_0)
91
    .dw (_int_sti_gpi_1)
92
    .dw (_int_sti_gpi_2)
93
    .dw (_int_sti_gpi_3)
94
    .dw (_int_sti_timer_d)
95
    .dw (_int_sti_timer_c)
96
    .dw (_int_sti_gpi_4)
97
    .dw (_int_sti_gpi_5)
98
    .dw (_int_sti_timer_b)
99
    .dw (_int_sti_transmit_error)
100
    .dw (_int_sti_transmit_buffer_empty)
101
    .dw (_int_sti_receive_error)
102
    .dw (_int_sti_receive_buffer_full)
103
    .dw (_int_sti_timer_a)
104
    .dw (_int_sti_gpi_6)
105
    .dw (_int_sti_gpi_7)
106
107
    ;///////////////////////////////////////////////////////////
108
    ; NMI Interrupt 0x66, muss mit retn abgeschlossen werden
109
    .org  adr_nmi
110
    jp _nmi_vint        ; Aufruf Handler im C Modul main.c
111
    retn
112
113
    ; //////////////////////////////////////////////////////////
114
    .org adr_copyright
115
    .asciz "(C) 02.2015 by C.Julius"
116
117
    ;///////////////////////////////////////////////////////////
118
    ; Anordung der Segmente fuer den Linker, ab hier nur relative
119
    ; Adressen
120
121
      .area  _CODE
122
      .area  _INITIALIZER
123
      .area  _HOME
124
      .area  _GSINIT
125
      .area  _GSFINAL
126
      .area  _DATA
127
      .area  _INITIALIZED
128
      .area  _BSEG
129
      .area  _BSS
130
      .area  _HEAP
131
132
; ---  Defintion der Heap Groesse
133
__sdcc_heap_start::
134
      .ds heap_size
135
136
      .area _HEAP_END
137
__sdcc_heap_end::
138
      .ds 1
139
140
    ;///////////////////////////////////////////////////////////
141
    ;; ------- Start des Init Codes ab hier -----------
142
143
    .area _CODE
144
    init:
145
146
    ld  sp,#stack       ;; Stack an Spitze des RAM legen
147
148
    ; Pruefe, ob ein Programm im RAM liegt
149
    ld a, (ram_prog)   ; Lade Start des RAM 0x4000
150
    cp #0xC3           ; vergleiche mit "C3" = JP Befehl
151
    jp Z, init2        ; Ja, dann nicht nullen
152
153
    ; Sonst Ram ausnullen
154
    xor     a                       ; clear a and carry
155
    ld      bc,#(0xffff-ram_prog)   ; ram size left
156
    ld      hl,#ram_prog            ; starting from 4000
157
    ld      de,#ram_prog+1
158
    ld      (hl),a        ; 0 -> (4000)
159
    ldir                  ; (HL) -> (DE)
160
161
    ; Normaler Programmstart ab hier
162
init2:
163
    ld  sp,#stack       ; Stack an Spitze des RAM legen
164
    call gsinit         ; Static Variablen
165
;   -------------------------------------------
166
    jp  _main           ; Hauptprogramm aufrufen
167
;   -------------------------------------------
168
169
; -----Globale Initialisierungen (Code liegt hinter Code Segment)------------
170
171
    .area  _GSINIT
172
173
gsinit:     ; Initialisiere globale Variablen im RAM
174
    call __sdcc_heap_init     ; Initialisiere den HEAP
175
176
    ld  bc, #l__INITIALIZER
177
    ld  a, b
178
    or  a, c
179
    jr  Z, weiter
180
    ld  de, #s__INITIALIZED
181
    ld  hl, #s__INITIALIZER
182
    ldir
183
184
weiter:
185
186
    ; // Hier muss ein ret rein
187
    .area _GSFINAL
188
    ret
189
    ;Markiert das Ende des Programmes
190
    .ascii "Z80END"

von Christian J. (Gast)


Lesenswert?

@Philipp:

Hast Du evtl noch eine Version vom sdcc von 2015 ? Wo alles noch so war 
wie als ich das Projekt angefangen habe? Also Also void putchar (char) 
und nur 1 Unterstrich bei Heap Global?

Ich glaube damit werde ich glücklicher, es funktionierte ja schliesslich 
auch.
Aktuell ärger ich mch nur herum 4 ganze Projekte irgendwie wieder ans 
Laufen zu bekommen. Habe leider keine in den snapshots mehr gefunden, 
die sind alle neu.

Gruss,
Christian

von Philipp Klaus K. (pkk)


Lesenswert?

Christian J. schrieb:
> @Philipp:
>
> Hast Du evtl noch eine Version vom sdcc von 2015 ? Wo alles noch so war
> wie als ich das Projekt angefangen habe? Also Also void putchar (char)
> und nur 1 Unterstrich bei Heap Global?
>
> Ich glaube damit werde ich glücklicher, es funktionierte ja schliesslich
> auch.
> Aktuell ärger ich mch nur herum 4 ganze Projekte irgendwie wieder ans
> Laufen zu bekommen. Habe leider keine in den snapshots mehr gefunden,
> die sind alle neu.
>
> Gruss,
> Christian

3.5.0 ist von 2015.

Als Quellen hier:

https://sourceforge.net/projects/sdcc/files/sdcc/3.5.0/

Binärdateien für diverse Systeme mit ein paar weiteren Klicks von:

https://sourceforge.net/projects/sdcc/files/

Philipp

von Philipp Klaus K. (pkk)


Lesenswert?

Christian J. schrieb:
> Philiiiiiiip........
>
> habt ihr schon wieder am sdcc rumgespielt? Naa...... ?
>
> Aslink Warning-Undefined Global ::sdcc_heap_init referened by module
> crt0

Das war aber schon im  Oktober 2015. Aus den Release Notes von 3.6.0:
"New memory management with lower overhead".

Um die Größe des Heap für z80 auf etwas anderes als 1KB zu ändern: 
heap.s anpassen und dazulinken. In der crt0 findet sich nun nichts mehr 
zum Heap.

Philipp

von Christian J. (Gast)


Lesenswert?

Hi,

ok. Kann ich also im Startup alles weglassen was den Heap betrifft und 
er ist dann 1kg gross? Das ginge natürlich auch. Die AREA liegt ja ganz 
oben, er müsste dann also unter dem Stack zu liegen kommen und über den 
Variablen (BSS).

edit: Klasse, mit dem 2015er alles wieder wie gehabt :-)

Gruss,
Christian

von Christian J. (Gast)


Lesenswert?

Hallo,

ist das normal, dass so eine Funktion vom Compiler nicht eleminiert 
wird? Im Asm Code finde ich trotz maximaler Optimierung ständig Aufrufe 
der "eingepackten" Funktion. Dabei wäre es doch einfach die umgebenden 
Verpackung komplett weg zu lassen. Die ist nur aus Gründen der 
Übersichtlichkeit da.

static void mcurses_putc (uint8_t ch)
{
    putchar (ch);
}

 4E42                     104 _mcurses_putc:
                            105 ;mcurses.c:70: putchar (ch);
   4E42 21 02 00      [10]  106   ld  hl, #2+0
   4E45 39            [11]  107   add  hl, sp
   4E46 7E            [ 7]  108   ld  a, (hl)
   4E47 F5            [11]  109   push  af
   4E48 33            [ 6]  110   inc  sp
   4E49 CD 7A 43      [17]  111   call  _putchar
   4E4C 33            [ 6]  112   inc  sp
   4E4D C9            [10]  113   ret

Hier steht was davon, dass der GCC für Z80 portiert werden soll, wäre 
natürlich stark wenn die Leistungsfähigkeit des GCC für Z80 da wäre aber 
vermutlich sind da wieder tausend andere Hürden "compiler spezifischer 
Erweiterungen". Nur bisher keine Files hinterlegt.

https://sourceforge.net/projects/z80gcc/

von S. R. (svenska)


Lesenswert?

Christian J. schrieb:
> Hier steht was davon, dass der GCC für Z80 portiert werden soll,

Die Chance, dass der gcc jemals ein Z80-Backend bekommen wird, schätze 
ich als äußerst gering ein. Für den LLVM stehen die Chancen ein wenig 
besser, siehe z.B. 
https://olduino.wordpress.com/2014/12/30/llvm-for-the-z80-another-source-of-inspiration/

Aber ob diese Backends jemals die Reife vom SDCC erreichen, hängt davon 
ab, ob die Retro-Welle lange genug anhält. ;-)

von Christian J. (Gast)


Lesenswert?

S. R. schrieb:
> Aber ob diese Backends jemals die Reife vom SDCC erreichen, hängt davon
> ab, ob die Retro-Welle lange genug anhält. ;-)

Der Verkauf von Plattenspielern und Vinyl Platten ist seit 2015 
"explodiert".

https://www.conrad.de/de/usb-plattenspieler-dual-dtj-3012-usb-direktantrieb-schwarz-1314095.html?gclid=Cj0KEQjww7zHBRCToPSj_c_WjZIBEiQAj8il5JtIMrpnW_oQozN1Y8228Ni0vMDIIqXhv3mPwODah_EaAjFS8P8HAQ&insert_kz=VQ&hk=SEM&WT.srch=1&WT.mc_id=google_pla&s_kwcid=AL!222!3!190748622382!!!g!!&ef_id=Vzv9rQAABPfxu2cz:20170413165922:s

Da ist es doch zu hoffen, dass auch hier eine "Entschleunigung" 
eintritt, weg vom MIPS und Cortex, hin zum Kaffee kochen beim 
Compilieren und dem leisen Stampfen der Takte im Zylinder des CPU 
Cores..... wenn ich mein Ohr an die Z80 lege höre ich es ganz deutlich! 
ticker...ticker....ticker...klick :-)

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

Wäre es programmtechnisch möglich, dass der SDCC auch mehrere Cores 
nutzt, so wie der GCC auch?  Und ihr es irgendwie hinkriegt, dass er 
nicht benutzten Code auch eliminiert?

Der Unterschied von --max-allocs-per-node 10000 zu 1 Mio beträgt 500 
Bytes auf 12kb Code aber die Laufzeit steigt von 1 Minute auf ca 15 
Minuten.

von S. R. (svenska)


Lesenswert?

Christian J. schrieb:
> Wäre es programmtechnisch möglich, dass der SDCC auch mehrere Cores
> nutzt, so wie der GCC auch?

Das ist nicht so einfach, wie du dir das vorstellst... und davon 
abgesehen für die meisten Anwendungsfälle sinnfrei.

Mir wäre es neu, dass der gcc mehrere Kerne nutzt. Üblicherweise besteht 
ein Projekt nämlich aus mehreren Dateien, und "make" ist in der Lage, 
automatisch mehrere Compilerinstanzen parallel laufen zu lassen.

Aber dazu müsste man sich ja in die verwendete Technologie einarbeiten, 
was du ja gerne und lautstark vermeidest.

von Philipp Klaus K. (pkk)


Lesenswert?

Christian J. schrieb:
> Wäre es programmtechnisch möglich, [… dass …] ihr es irgendwie
> hinkriegt, dass er nicht benutzten Code auch eliminiert?

Da sind 3 Fälle zu unterscheiden:

1) Ungenutzer Code in Funktionen, wo sich ohne Kenntnis der anderen 
Funktionen erkennen lässt, dass der Code ungenutzt ist. Das ist die 
klassische Dead Code Elimination, die der SDCC beherrscht (aber 
natürlich ließe sich die noch effektiver machen, z.B. durch bessere 
Zeigeranalyse oder durch Intervallanalyse).

2) Nicht aufgerufene Funktionen, die static oder inline (aber nicht 
inline und extern zugleich) sind. Das erfordert zwar deutliche 
Änderungen im Compiler, ist aber vorgesehen (aber erst für irgendwann 
nach SDCC 3.7.0). Siehe auch den Thread "Keeping functions (and maybe 
other things) 'to be emitted later'? Multiple passes?" auf sdcc-devel.

3) Andere nicht aufgerufene Funktionen. Das erfordert Änderungen an 
Compiler und Linker. Das ist etwas, das wir zwar gern hätten, allerdings 
gibt es erstmal zuviel wichtigeres zu tun, so dass es wohl länger dauern 
wird.
Es gibt hier allerdings einen Workaround: Wenn alle Funktionen in 
einer.rel nicht aufgerufen werden, und die .rel zuerst in eine 
Bibliothek eingebunden wird, und dann die Bibliothek zum Rest des 
Programms gelinkt wird, funktioniert es schon. Wenn man also die 
Fuktione sinnvoll gruppert auf C-Dateien aufteilt, lässt sich das 
Gewünschte erzielen. Di Standardbibliothek ist z.B. so aufgeteilt, und 
somit werden nur die wirklich benötigten Teile der Standardbibliothek 
eingebunden.

Philipp

von Christian J. (Gast)


Lesenswert?

Hallo Philipp,

danke für Dein Feedback. Wäre so ein Compiler nicht so ein extrem 
komplexes Werk würde ich da schon lange mitmachen wollen. Ich habe 
Respekt vor denjenigen, die ihre Freizeit dafür opfern da erstens 
durchzusteigen und zweitens noch jene im Nacken zu haben, die gern alles 
anders hätten.
Mir ist zb aufgefallen, dass keine Elimination ganz kleiner Funktionen 
stattfindet, sondern dass wirklich stur jede Funktion mit Call und 
Registersicherung abgearbeitet wird, auch wenn sie nur 3 Befehle 
enthält.

Ein Multithreading muss ja nicht sein, ich habe es nur zufällig gesehen 
dass der GCC es kann bzw der Linker beim Kompilieren des sdcc.

Wie man eigene Libs erzeugt muss ich mir erst noch anschauen. Habe das 
noch nie gemacht in 25 Jahren C Programmieren.

Der erzeugte Z80 Code ist aber klasse, sieht wirklich alles sehr optimal 
aus! Man merkt sofort wo man selbst noch Hand anlegen muss bei der 
Durchsicht der .lst Dateien.

von Philipp Klaus K. (pkk)


Lesenswert?

Christian J. schrieb:

> Mir ist zb aufgefallen, dass keine Elimination ganz kleiner Funktionen
> stattfindet, sondern dass wirklich stur jede Funktion mit Call und
> Registersicherung abgearbeitet wird, auch wenn sie nur 3 Befehle
> enthält.

Zu entscheiden, dass in solchen Fällen die durch inline-Ersetzung 
wegoptimiert werden, wäre Aufgabe der inlining-Heuristik. Die von GCC 
würde das machen.
Und auch für den SDCC ist es vorgeshen, so etwas (also eine 
inlining-Heuristik, die inline-Ersetzung beim Aufruf sehr kleiner 
Funktionen vornimmt) nach 3.7.0 zu implementieren. Auch dafür werden die 
in "Keeping functions (and maybe
other things) 'to be emitted later'? Multiple passes?" besprochenen 
Änderungen gebraucht.

Zur Zeit berücksichtigt die inlining-Heuristik in SDCC die Größe der 
aufgerufenen Funktionen nicht:

inline-Ersetzung von Funktionsaufrufen in SDCC findet genau dann statt, 
wenn der Funktionsaufruf nicht über Funktionszeiger erfolgt, die 
Funktion eine feste Anzahl an Argumenten hat, und die Funktion mit dem 
Schlüsselwort inline definiert ist.

Philipp

von Philipp Klaus K. (pkk)


Lesenswert?

Christian J. schrieb:
> Hallo,
>
> ist das normal, dass so eine Funktion vom Compiler nicht eleminiert
> wird? Im Asm Code finde ich trotz maximaler Optimierung ständig Aufrufe
> der "eingepackten" Funktion. Dabei wäre es doch einfach die umgebenden
> Verpackung komplett weg zu lassen. Die ist nur aus Gründen der
> Übersichtlichkeit da.
>
> static void mcurses_putc (uint8_t ch)
> {
>     putchar (ch);
> }
>
>  4E42                     104 _mcurses_putc:
>                             105 ;mcurses.c:70: putchar (ch);
>    4E42 21 02 00      [10]  106   ld  hl, #2+0
>    4E45 39            [11]  107   add  hl, sp
>    4E46 7E            [ 7]  108   ld  a, (hl)
>    4E47 F5            [11]  109   push  af
>    4E48 33            [ 6]  110   inc  sp
>    4E49 CD 7A 43      [17]  111   call  _putchar
>    4E4C 33            [ 6]  112   inc  sp
>    4E4D C9            [10]  113   ret

Irgendwann nach 3.7.0 soll das automatisch optimiert werden. Zur Zeit 
klappt es nur, wenn da (statt oder zusätzlich zu "static") auch "inline" 
steht.

Philipp

von Philipp Klaus K. (pkk)


Lesenswert?

Christian J. schrieb:
> Hi,
>
> ok. Kann ich also im Startup alles weglassen was den Heap betrifft und
> er ist dann 1kg gross?

Das sollte gehen; der Heap wäre dann 1 KB groß.

Philipp

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.