2013-04-10 22 views
5

Ho un po 'di codice assembly PowerPC tradotto con un cross compiler gcc con questa funzione:Come sopprimere "attenzione: il controllo raggiunge il termine della funzione non-vuoto"

uint32_t fill_cache(void) 
{ 
    __asm__ ("addi 3, 0, 0\n"); /* R3 = 0 */ 
    /* More asm here modifying R3 and filling the cache lines. */ 
} 

che, sotto il PowerPC EABI, restituisce il valore calcolato in R3. Quando compilo ottengo

foo.c:105: warning: control reaches end of non-void function 

C'è un modo per insegnare a gcc che un valore viene effettivamente restituito? O c'è un modo per sopprimere l'avviso (senza rimuovere -Wall o aggiungendo -Wno- *)? Mi piacerebbe sopprimere molto selettivamente questo avviso solo per questa funzione per lasciare il livello di avviso generale più alto possibile.

Non è un'opzione per rendere questa funzione non valida poiché il chiamante richiede il valore calcolato.

risposta

12

Soluzione 1: con diagnostic pragmas è possibile sopprimere localmente alcuni controlli diagnostici. L'opzione specifica (che è anche implicita da -Wall) che lamenta la mancata restituzione in una funzione non vuota è -Wreturn-type. Quindi il codice specifico per eliminare l'avviso è:

#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wreturn-type" 
/* Your code here */ 
#pragma GCC diagnostic pop 

Si può scoprire quale opzione sta causando l'avviso compilando con -fdiagnostics-show-opzione. Semplicemente aggiungerà l'opzione al messaggio di avviso.

Soluzione 2: definire uno register variable e inserirlo nel registro desiderato. Fare riferimento alla variabile in un inline assembler template, con il codice risultante:

uint32_t fill_cache(void) 
{ 
    register uint32_t cacheVal __asm__ ("r3"); 

    __asm__ __volatile__ ("addi %0, 0, 0" : "=r" (cacheVal)); 
    /* More code here */ 

    return cacheVal; 
} 

La volatilità modificatore è quello di garantire che l'istruzione non viene rimosso o in altro modo influenzato indesiderabilmente dalla strategia di ottimizzazione.

Soluzione 2 è preferibile per almeno due motivi:

  1. Il valore di mancato funzione non-ritorno vuoto è indefinito quanto lo standard è interessato.
  2. Non c'è alcun rischio di sopprimere (nuovi) avvisi diagnostici, non c'era intenzione di sopprimere in primo luogo.
1

funzione potrebbe essere dichiarato come naked, in questo caso compilatore non genererebbe prologo & epilogo e assumerebbe che programmatore conserva tutti i registri necessari e mette in valore di uscita corretto registro (s) prima di ritorno.

uint32_t fill_cache(void) __attribute__((naked)); // Declaration 
// attribute should be specified in declaration not in implementation 

uint32_t fill_cache(void) 
{ 
    __asm__ ("addi 3, 0, 0\n"); /* R3 = 0 */ 
    /* More asm here modifying R3 and filling the cache lines. */ 
} 

Un po 'in ritardo ma forse qualcuno farà un passo in questo pure :)

PS: Per la mia conoscenza migliore __asm__ così come __volatile__ sono std=c89 sintassi. In pratica non c'è differenza tra __asm__ & asm in GNU GCC. Ma l'approccio moderno è senza stile: asm volatile.

asm_language