Come posso testare l'assemblaggio generato?

0

Sto lavorando su un compilatore C per Linux allo scopo di curiosità personale / divertimento. Come posso testare l'assembly generato prima che il compilatore sia abbastanza completo da fare qualcosa di utile?

Ad esempio, se ho il seguente programma:

int a = 1;

e viene compilato per

a:
    .long 1

Come posso essere sicuro che questa uscita sia effettivamente la cosa giusta da fare? La mia ipotesi è che i modi in cui si può normalmente interagire con il codice compilato siano caratteristiche relativamente avanzate (ad es. I / O, libreria statica, ecc.) Che sono meglio implementate in una fase successiva.

Qualche trucco qui?

    
posta JETM 09.08.2018 - 00:30
fonte

2 risposte

4

In generale, non "testerai" (in realtà, in questo senso, una parola migliore è controllo e probabilmente controllo statico , relativo a analisi del programma statico ) analizzando staticamente l'assemblatore senza eseguire il programma compilato, perché è troppo difficile. Tuttavia, potresti avere degli script di test che analizzano l'assemblatore generato per un determinato programma di input e ne controllano la struttura (non penso che sia saggio farlo ...).

In pratica, la maggior parte dei compilatori ha una vasta suite di test. Se stai codificando un compilatore per alcuni linguaggi esistenti (ad esempio se stai codificando un compilatore C), potresti provare a riutilizzarli (ad esempio, GCC ha una suite di test ben consolidata che è possibile adattare al compilatore, alcuni test infatti" analizzano "l'assembly generato o la diagnostica emessa).

Tuttavia, guarda anche al progetto CompCert che tratta di un compilatore C formalmente verificato (una parte importante di questo lavoro è la formalizzazione della semantica di C e del comportamento del compilatore).

How can I test the generated assembly before the compiler is complete enough to do anything useful?

Probabilmente non puoi farlo, se non tramite l'ispezione manuale di quel codice assembly. Probabilmente vorresti lavorare per ottenere, il più rapidamente possibile, una piccola parte del tuo linguaggio compilabile (per alcuni programmi che potresti testare). Ad esempio, potresti decidere di lavorare sodo per rendere compilabile il programma vuoto, quindi di compilare un programma di assegnazione singola su 1 riga, quindi di compilare alcuni piccoli programmi di 5 righe, ecc ... Quindi il tuo compilatore avrebbe una sequenza crescente di test suite.

Potresti voler compilare il tuo compilatore con se stesso. Questa è una lunga tradizione (e quindi la possibilità di compilare il compilatore è un test valido). Leggi compilatori bootstrap (e guarda nel blog di J.Pitrat a proposito di bootstrapping artificial intelligence ; ha molte pagine interessanti).

Potresti anche basare il tuo lavoro di compilatore sopra una libreria di "compilazione" come libgccjit o LLVM , o scegli compila a C (o a qualche altra lingua, livello più alto dell'assemblaggio). Ciò potrebbe farti risparmiare molti sforzi.

Si noti che, in pratica, i compilatori C dovrebbero essere ottimizzati, ed è per questo che è difficile competere con i compilatori esistenti. Vedi anche questo .

    
risposta data 09.08.2018 - 07:23
fonte
1

How can I be sure that this output is actually the correct thing to do?

Se capisco cosa stai chiedendo correttamente, non puoi. Il comportamento corretto del tuo programma deriva dalla tua comprensione del problema che tenta di risolvere. Il test convalida che l'implementazione corrisponde alla tua comprensione ma non fa nulla per convalidare la tua comprensione.

Una comprensione imperfetta dell'aritmetica di base che hai creduto in add(2, 3) dovrebbe restituire 6 ti porterà a scrivere codice per farlo e un test corrispondente per verificare che effettivamente lo faccia. Quel test sarebbe passato e tutto sarebbe andato bene. (Oppure, se stai facendo TDD, devi prima scrivere il test, fallire e poi aggiustare il codice in modo che il test passi.) L'implementazione, pur verificabile in relazione al requisito, si basa su un requisito imperfetto. Garbage in, garbage out si applica tanto al codice di sviluppo quanto ai dati di elaborazione.

    
risposta data 09.08.2018 - 19:40
fonte

Leggi altre domande sui tag