All’interno del file axe_utils.c tra le righe 98-101, il commento sembra indicare che si procede ad emettere una istruzione di LOAD
per una variabile scalare:
/* add a load instruction for each declared variable
* that is not an array type */
if (!(current_decl->isArray))
get_symbol_location(program, current_decl->ID, 0);
La funzione get_symbol_location()
, fra le altre cose, dovrebbe generare un’istruzione di LOAD
per la variabile, mentre per come viene invocata (l’ultimo parametro passato – genLoad
–, è uno 0) non lo fa.
Visto che l’istruzione di LOAD
è indispensabile non capisco come le cose possano funzionare.
Ad esempio:
int a = 2;
write(a);
Come viene gestita la LOAD
in questo caso?
Analizzando la dichiarazione della variabile a
il compilatore ACSE compie due azioni:
a
a
Entrambe le azioni vengono svolte nella funzione set_new_variables
.
In un primo momento – axe-utils.c:69-84 – si scorre la lista di tutte le variabili dichiarate e si crea la struttura per rappresentarle.
La funzione createVariable
serve a questo.
I parametri notevoli che le vengono passati sono due:
current_decl->ID
current_decl->init_val
Tramite createVariable
ACSE registra tale informazioni nella symbol table.
Per ora non fa null’altro a livello di generazione del codice, ma queste informazioni gli serviranno in seguito.
Dopo una prima scansione della lista delle variabili se ne fa un’altra – axe-utils.c:90-108 – nella quale si crea un registro temporaneo per allocare le variabili scalari.
Tale azione viene eseguita dalla funzione get_symbol_location
.
Il commento in axe-utils.c:98-99 è un errore di scrittura: non viene generata nessuna LOAD
.
Alla fine della funzione set_new_variables
il compilatore ha segnato in una sua struttura dati interna tutte le variabili dichiarate, e nel caso di variabili scalari ha anche allocato un registro temporaneo per contenerle.
Non ha emesso alcuna istruzione!
Successivamente viene riconosciuta l’istruzione write
e viene generato il codice per stampare il contenuto di a
.
A questo punto il codice generato è:
WRITE R1 0
Dove R1
è il registro temporaneo destinato a contenere a
.
La LOAD
non è ancora stata generata
Proseguendo con l’analisi del programma, ad un certo punto si consuma tutto l’input e il parser termina: la funzione yyparse
ritorna al chiamante, nel nostro caso il main – Acse.y:582.
Per completare la traduzione il compilatore deve eseguire alcune operazione finali.
Una di queste è generare il codice per l’inizializzazione delle variabili.
Esso viene emesso all’interno della funzione updateProgramInfos
, richiamata in Acse.y:643.
A questo punto il codice generato è completo, e quindi abbiamo:
LOAD R1 L0
WRITE R1 0
STORE R1 L0
HALT
La LOAD
è comparsa solo ora.
Essa è stata generata consultando le informazioni che ACSE aveva raccolto all’interno della funzione set_new_variables
.
Queste LOAD
sono particolari e quindi è stata necessario gestirle separatamente all’interno del compilatore.
Per quanto riguarda il corso non ci sono problemi, basta sapere che esistono.