2016-06-26 1 views
15

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.htmlLa "copia garantita Elision" (P0135, C++ 1z) potrebbe richiedere la rottura dell'ABI?

La suddetta proposta di 'garantito Copy Elision' stato votato nel C++ documento di lavoro nella riunione di giugno 2016 Oulu, in Finlandia, che è stato poi votato per la pubblicazione come bozza comitato. Spero che questo porti alla pubblicazione come standard C++ 17 il prossimo anno.

La proposta chiarisce varie categorie di valori che coinvolgono oggetti temporanei, per far rispettare l'assenza di chiamate al costruttore di copia in determinati casi d'uso.

La mia domanda è "questo nuovo requisito potrebbe interrompere la compatibilità ABI per i compilatori che in precedenza non avrebbero potuto eseguire la copia elision in queste circostanze o averlo implementato in un modo che non sarebbe compatibile con i nuovi requisiti?"

Sto pensando a cose come le inizializzazioni che elidono le copie quando la creazione di un oggetto può essere sottolineata, ma non quando si attraversano i confini delle unità di compilazione.

+4

Posso immaginare un ABI (se ridicolo) che sarebbe rotto da questo cambiamento. Sarebbe sufficiente o stai cercando istanze reali di un ABI effettivamente utilizzato da un compilatore non giocattolo che si rompe? – Yakk

+4

Come si può rompere qualcosa che non esiste? – user3104201

+0

"* Sto pensando a cose come le inizializzazioni che elidono le copie quando la creazione di un oggetto può essere sottolineata, ma non quando incrocio i confini delle unità di compilazione. *" Non conosco tali circostanze in cui ciò sarebbe possibile. –

risposta

11

Quando viene chiamata una funzione, la funzione deve restituire un valore. Quel valore ha bisogno di memoria per vivere, ma il valore di ritorno deve sopravvivere alla funzione stessa. L'ABI definisce come funziona tutto questo. In generale, ciò avviene quando il chiamante fornisce un pezzo di memoria della dimensione/allineamento per il valore restituito alla funzione.

Quindi, se una funzione calcola un valore e lo restituisce, deve (in teoria) copiare quel valore calcolato nella memoria del valore di ritorno. E quando il chiamante lo recupera, deve (in teoria) copiare la memoria del valore di ritorno in qualche altro oggetto stack per un uso successivo.

L'elisione di copia non garantita dice che nessuna di queste copie è necessaria. Sul lato della funzione di ritorno, al compilatore è permesso utilizzare semplicemente la memoria del valore di ritorno internamente quando genera quel valore, quindi l'istruzione return non deve copiare nulla. E sul lato ricevente, se la memoria verrà utilizzata per inizializzare un oggetto stack, non dovrà copiare in quella memoria.

L'elisione di copia garantita dice che se il lato ricevente sta inizializzando un oggetto dello stesso tipo, il ricevitore non considererà se l'oggetto ha un costruttore copia/sposta. Pertanto, il codice che chiama una funzione come auto t = Func(); non lo considererà come una potenziale operazione di copia in t. Il compilatore che elabora il codice chiamerà Func con la memoria del valore di ritorno che si trova nello spazio di stack per t.

E sul lato chiamato, se si restituisce direttamente un valore nominale, non è necessario che esista un costruttore copia/sposta. Il callee costruirà il valore nominale direttamente nella memoria del valore di ritorno.

Ecco la cosa: agli ABI non importa nulla di tutto ciò. Tutto ciò a cui ABI si preoccupa è la memoria di basso livello. Cioè, fintanto che il chiamante sta passando la memoria del valore di ritorno della dimensione e dell'allineamento appropriate e il callee sta inizializzando quella memoria con un oggetto del tipo appropriato ... l'ABI non si cura di.

Se il chiamante desidera utilizzare la memoria del valore di ritorno per operazioni successive, ciò va bene per l'ABI. Se il destinatario desidera inizializzare i dati direttamente nella memoria del valore di ritorno invece di copiarlo, l'ABI non se ne accorgerà.

L'ABI definisce l'interfaccia; quello che fai con questa interfaccia dipende da te.

Ad esempio, considerare Itanium ABI on return values. Permette di memorizzare i tipi di classe nei registri, ma solo se dispongono di semplici costruttori di copia/spostamento. In caso contrario, indipendentemente dal loro contenuto, devono essere costruiti nella memoria fornita dalla funzione chiamante. Se la classe è banalmente riproducibile, non è possibile distinguere tra elisione e non elisione.

L'unico modo in cui un ABI può porre un problema a questa funzione è se l'ABI ha deciso arbitrariamente dove il valore di ritorno (e presumibilmente i parametri) è memorizzato, l'uno rispetto all'altro. Cioè, l'ABI costringe il chiamante a posizionare l'oggetto sullo stack in una posizione specifica rispetto ai parametri.

Potrebbe esistere un ABI simile? Non ho alcuna conoscenza particolare per dire che non può. Lo fa? Ne dubito piuttosto, dato che un tale ABI renderebbe difficile l'elisione in generale.

+0

La domanda si riduce quindi alla presenza o meno di compilatori esistenti che implementano la memoria del valore di ritorno in modo stupido che potrebbe rovinare sia il call che scrive il risultato direttamente in esso sia il chiamante che utilizza il risultato direttamente da esso. – Novelocrat

+0

@Novelocrat: l'ABI definisce come i valori vengono passati meccanicamente attraverso le chiamate di funzione. L'unico modo in cui potrebbe essere rovinato è se un compilatore non stava seguendo l'ABI. Che è un problema molto più grande di non riuscire a implementare correttamente l'elision garantito. –

+3

@Nicol: se invece di consentire al chiamante di specificare una posizione arbitraria in cui verrà inserito il valore di ritorno, l'ABI lo specifica rispetto a qualcos'altro (posizione dei parametri, indirizzo di ritorno, ecc.). Quindi il chiamante potrebbe non essere in grado di evitare un successivo trasferimento dalla posizione definita da ABI (che potrebbe essere sovrascritta da chiamate di funzioni aggiuntive prima della fine dell'oggetto) in una posizione di maggiore durata. –

Problemi correlati