Jakie są etapy kompilacji programu C++?

Czy etapy kompilacji programu C++ są określone przez standard?

Jeśli tak, to czym one są?

Jeśli nie, ODPOWIEDŹ dla szeroko używanego kompilatora (wolałbym MSVS) byłaby świetna.

Mówię o preprocessingu, tokenizacji, parsingu i tym podobnych. Jaka jest kolejność ich wykonania i co robią w szczególności?

EDIT: wiem co robi kompilacja, linkowanie i preprocessing, interesuje mnie głównie reszta i spokój. Wyjaśnienia są oczywiście mile widziane, ponieważ być może nie tylko ja jestem zainteresowany odpowiedzią.

Author: sbi, 2012-01-12

3 answers

Czy etapy kompilacji programu C++ są określone przez standard?

Tak i nie.

Standard C++ definiuje 9 "faz tłumaczenia". Cytowanie z projektu n3242 (10MB PDF), z dnia 2011-02-28( przed wydaniem oficjalnego standardu C++11), sekcja 2.2:

Pierwszeństwo wśród reguł składniowych tłumaczenia jest określone przez następujące fazy [patrz przypis] .

  1. fizyczny plik źródłowy znaki są mapowane, w sposób zdefiniowany w implementacji, do podstawowego zestawu znaków źródłowych (wprowadzenie znaków nowego wiersza dla wskaźników końca wiersza), jeżeli konieczne. [SNIP]
  2. każde wystąpienie odwrotnego ukośnika ( \ ), po którym następuje znak nowej linii, jest usuwane, łącząc fizyczne linie źródłowe z tworzą logiczne linie źródłowe. [SNIP]
  3. plik źródłowy jest rozkładany na tokeny wstępnego przetwarzania (2.5) i sekwencje białej przestrzeni postaci (w tym Komentarze). [SNIP]
  4. wykonywane są dyrektywy przetwarzania wstępnego, wywołania makr są rozszerzane i wykonywane są wyrażenia operatorowe _pragma. [SNIP]
  5. każdy element zestawu znaków źródłowych w literale lub łańcuchu znaków, a także każda sekwencja escape i uniwersalna-nazwa-znaku w literale znakowym lub nie-surowym ciągiem literalnym, jest konwertowany na odpowiadający element zestawu znaków wykonania; [SNIP]
  6. sąsiadujące ze sobą znaki znaków literalnych są łączone.
  7. znaki oddzielające żetony nie mają już znaczenia. Każdy token wstępnego przetwarzania jest konwertowany na token. (2.7). Na powstałe tokeny są analizowane składniowo i semantycznie oraz tłumaczone jako jednostka tłumaczeniowa. [SNIP]
  8. tłumaczone jednostki tłumaczeniowe i instancje są połączone w następujący sposób: [SNIP]
  9. wszystkie zewnętrzne byty referencje są rozwiązane. Komponenty Biblioteki są połączone w celu zaspokojenia zewnętrznych odniesień do podmiotów nie zdefiniowanych w aktualne tłumaczenie. Wszystkie takie wyjścia tłumacza gromadzone są w obraz programu, który zawiera informacje potrzebne do wykonania w swoim środowisko wykonawcze.

[footnote] implementacje muszą zachowywać się tak, jakby te oddzielne fazy występowały, chociaż w praktyce różne fazy mogą być złożone razem.

Jak wskazano w [SNIP] markery, nie zacytowałem całego fragmentu, tylko na tyle, żeby pomysł się pojawił.

Aby podkreślić, Kompilatory są Nie wymagane do przestrzegania tego modelu, o ile końcowy wynik jest taki, jakby tak było.

Fazy 1-6 odpowiadają mniej więcej preprocesorowi, 7-kompilacji, 8-szablonom, a 9-linkom.

(fazy translacji C są podobne, ale # 8 jest pominięty.)

 35
Author: Keith Thompson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-12 21:26:44

9 tzw. "faz tłumaczenia" jest wymienionych w standardzie w [lex.phases] (2.2 W C++11, 2.1 W C++03).

Szczegóły wymagane w standardzie są różne: przetwarzanie wstępne jest podzielone na kilka faz, ponieważ ważne jest w różnych punktach standardu dokładnie to, co zostało "już zrobione" i co jest "pozostawione do zrobienia", gdy określony bit zachowania jest zdefiniowany. Więc chociaż nie mówi ci, jak napisać leker, daje dość jasny plan działania.

Linkowanie na druga ręka jest pozostawiona głównie do implementacji, aby zdecydować, jak to jest rzeczywiście osiągnięte, ponieważ standard nie obchodzi Jak dana nazwa jest sprawdzana, tylko to, co odnosi się do.

Nie podaje żadnych szczegółów dotyczących parsowania, po prostu mówi "wynikowe tokeny są składniowo i semantycznie analizowane i tłumaczone". To dlatego, że cały rozdziały 3-15 są wymagane, aby wypełnić ten szczegół.

Nie wspomina o reprezentacjach wewnętrznych podczas parsowanie/tłumaczenie w ogóle, ani nie wspomina o fazach optymalizacji -- są one ważne dla projektowania kompilatorów, ale nie są ważne dla standardu. Optymalizacja może występować w różnych miejscach w różnych kompilatorach. Przez długi czas optymalizacja była prawie w całości w fazie kompilacji, przed emisją plików obiektowych, a linkery były głupie jak post. Myślę, że teraz poważne implementacje C++ mogą zrobić przynajmniej pewną optymalizację w wielu TUs. Więc "inni" nie są po prostu pozostawione poza standardem, faktycznie zmieniają się w czasie.

 6
Author: Steve Jessop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-12 11:04:37

Specyfikacja C++ jest celowo niejasna pod wieloma względami, głównie po to, aby zachować niezależność od implementacji. Wiele obszarów, w których język jest niejasny, nie jest już dużym problemem - na przykład zwykle można polegać na znaku 8 bitów. Jednak inne kwestie, takie jak układ struktur, które używają dziedziczenia wielokrotnego, są prawdziwym problemem, podobnie jak implikacje funkcji wirtualnych na klasach. Problemy te wpływają na kompatybilność kodu generowanego z różnymi kompilatorami. Na Binarny interfejs aplikacji (lub ABI) w C++ nie jest ściśle zdefiniowany i w rezultacie czasami trzeba zanurzyć się w C, gdzie staje się to problematyczne. Pisanie interfejsu wtyczki jest dobrym przykładem.

Podobnie, standard nie podaje szczegółowego opisu jak kompilator powinien być zbudowany, ponieważ istnieje wiele kluczowych decyzji i funkcji, które różnicują Kompilatory. Na przykład, MSVC może wykonywać częściowe Kompilacje (zezwalając na edycję i kontynuację), czego GCC nie robi. Ogólnie rzecz biorąc jednak wszystkie Kompilatory wykonują podobne etapy: wstępne przetwarzanie, analizowanie składni, określanie przepływu programu, tworzenie tabeli symboli i tworzenie liniowej serii instrukcji, które mogą być następnie połączone w celu wytworzenia pliku wykonywalnego. AHA, i linkowanie tych plików obiektowych, zwykle robi to linker.

Spojrzałem krótko, raczej trudno znaleźć opisy poszczególnych kompilatorów. Wątpię, że jest wiele na komercyjnych kompilatorach, takich jak oferta Microsoftu, wyłącznie dla powody handlowe. GCC jest najlepszym rozwiązaniem, chociaż Microsoft chętnie opisuje ten proces. jest to dość banalna rzecz: Kompilatory działają prawie tak samo. Prawdziwe złoto polega na tym, jak wykonują te etapy, algorytmy i struktury danych, których używają. Pod tym względem, polecam tę książkę . Kilka lat temu kupiłem zupełnie nowy egzemplarz na kurs uniwersytecki, a większość moich podręczników pożyczyłem z biblioteki :).

 3
Author: Liam M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-13 00:26:18