컴파일러 시리즈 섹션 2: GCC
6066 단어 cppccompilerscomputerscience
컴파일러는 처음에 GNU 운영체제를 위해 공급업체 컴파일러를 사용하지 않기 위해 허가증 비용을 지불했다.그때부터 그것은 인기와 성능에 있어서 전유 컴파일러를 넘어섰다.
사용자가 터미널에서
gcc myfile.c
같은 명령을 실행할 때 시작하는 과정은 4단계로 나눌 수 있다. 예처리, 컴파일, 조립, 링크이다.사전 프로세서 1
사전 프로세서 처리는 원본 코드를 컴파일하기 전에 수정합니다.우리는 C/C++ 프로세서를 전문적으로 연구할 것이다.다른 사전 프로세서 또는 프런트엔드는 위의 다른 언어에 사용할 수 있습니다.이 단계에서 일정량의 어법 변환이 발생할 것이다.다음과 같은 작업을 수행합니다.
회선 결합
줄 바꾸기를 사용하면 원본 코드의 줄을 정리합니다.줄 바꿈 문자는 줄을 구분하는 데 사용되는 반사봉입니다.그것들은 반드시 영패 사이나 주석 안에 나타나야 한다.
코드의 모든 주석도 단일 공백으로 대체됩니다.
표기화
이 변환이 완료되면 프로그램은 예비 프로세서 영패로 분해됩니다.이 영패들은 컴파일러에 전달될 것이며, 그곳에서는 컴파일러 영패로 사용될 것이다.현재 프로세서 영패는 표지부, 예처리 숫자, 문자열 문자, 문장부호와 기타 5가지로 나눌 수 있다.
명령 및 매크로 처리
이것은 대부분의 사람들이 C/C++ 프로세서와 관련된 절차로, 컴파일러 사용자들은 이 단계를 자주 본다.만약 영패가 예처리 언어에 아무런 내용도 포함되지 않는다면, 그것을 컴파일러에게 전달하기만 하면 된다.
다음은 사전 처리 언어에서 사용되는 일반적인 기능입니다.
헤더 파일 포함
헤더 파일에는 C/C++ 선언과 기타 프로세서 명령이 포함되어 있습니다.헤더 파일은 운영 체제에서 제공하여 시스템 API를 사용하거나 사용자가 정의할 수 있습니다.이것은 파일 간에 정의를 공유하는 것을 가능하게 한다.
만약 우리가 모든 중간 단계의 코드 출력을 본다면, 우리는 모든
#include <xyz.h>
이 xyz.h
의 내용으로 교체되는 것을 볼 수 있을 것이다매크로 처리
매크로는 클래스 대상일 수도 있고 클래스 함수일 수도 있다.유사한 대상의 매크로는 데이터 대상처럼 보인다.기호 상수 이름(예:
#define MAX_SIZE = 1024
)에 가장 많이 사용됩니다.코드에서 이름
MAX_SIZE
을 사용하면 사전 프로세서가 1024
으로 이 텍스트를 대체합니다클래스 함수 매크로는 사용할 때 함수 호출처럼 보입니다.그것들이'호출'될 때, 정의에 나타난 코드는 호출된 곳으로만 복사됩니다.예.
#define SQUARE(x) x*x
코드에 SQUARE(X)
이 나타나면 x*x
으로 교체됩니다. 그 중에서 x는 제곱으로 전달되는 값입니다.매크로는 성능을 향상시키는 데 사용됩니다.코드는 프로세서에 의해 복사된 것이기 때문에 어셈블리 출력에 함수 창고 등의 비용이 없습니다. 이 단락은 매크로의 표면과 매크로의 용도는 거의 없지만, 컴파일러의 기본 부분은 아닙니다.
조건 컴파일
이것은 프로세서가 다음 코드 부분을 컴파일러에 맡길지 여부를 결정할 수 있도록 합니다.어떤 경우, 이것은 경비를 포함하여 유용하다.같은 헤더 파일이 여러 번 복사되지 않도록 보호하는 것을 포함합니다.이것은 번역 속도를 가속화시켰다.
// An example include guard
#ifndef __MY_HEADER
#define __MY_HEADER
...
#endif
어셈블리 2
이것은 사전 처리 코드를 가져와 프로그램 집합을 만드는 단계입니다.gcc컴파일러는 입력 프로그램의 표시를 여러 번 전달하고 기계 코드를 출력하기 전에 서로 다른 중간 표시로 변환한다.
다음 그림은 3과 관련된 단계를 보여 줍니다.
분석 과정
이것은 컴파일러의 앞부분이다.위의 C 프로세서에 대한 자세한 내용은 이 단계에 적용됩니다.프로세서가 작업을 마친 후 컴파일러는 영패 흐름에서 추상적인 문법 트리(AST)를 생성합니다.현재는 입력 프로그램을 나타내는 트리 데이터 구조로 볼 수 있다.AST는 쉽게 수정하고 변환할 수 있기 때문에 입력의 내부 표현으로 사용할 수 있습니다.
모든 전단은 다른 방식으로 작동하지만, 일반적으로Generic (또는 GIMPLE) 라는 폼을 최종적으로 출력합니다.이 단계의 역사와 내부 작업은 약간 복잡하고 혼란스러운 것 같지만, 범용이 출력되어 컴파일러에 전달되기만 하면 우리는 매우 기쁘다.
확대 채널
이 절차는 범용 표현을 GIMPLE 표현으로 변환하는 것과 관련된다.그러나 이것은 AST보다 더 제한적인 또 다른 중간 표시이다.그것은 이후의 최적화 과정에 쓰인다.GIMPLE의 가장 기본적인 기능은 범용 표현식의 원조 집합을 나타내는 것이다.그 구조의 요점은 다음과 같다.
트리 SSA
이 단계는 우리가 현재 가지고 있는 코드의 내부 표시를 여러 번 전달하는 것과 관련된다.SSA는 단일 정적 할당을 나타냅니다.각 변수를 한 번만 할당하도록 GIMPLE 표현이 수정되었습니다.변수를 여러 번 할당해야 하는 경우 새 변수가 생성됩니다.
상기 gcc내부수첩 제9.4절에서 보듯이 이 절차는 47가지 서로 다른 최적화와 관련된다.순환 최적화, 조건, 접근할 수 없는 코드 삭제, 복잡해 보이는 다른 조작을 포함한다.이 단계에서 새로운 GIMPLE 표시로 돌아가면 변경 사항이 적용되고 다음 단계로 전달됩니다.
RTL 회사
RTL은 레지스터 전송 언어를 대표하며, 우리가 원하는 기계 코드 출력에 더욱 가깝다.GIMPLE는 RTL로 변환됨을 나타냅니다. RTL은 무한한 레지스터가 있는 추상적인 프로세서를 가정합니다.이런 형식에서 여러 차례 전달을 하여 코드를 더욱 최적화시켰다.최적화된 폼은 gcc 백엔드에 전달됩니다.
조립하다
전단과 같이 gcc는 많은 백엔드를 지원하는데 이런 백엔드는 플랫폼에 특정한 기계 코드의 출력을 처리한다.여기에는 x86, i386,arm이 포함됩니다.최적화된 RTL을 지정하면 백엔드에서 지정된 플랫폼의 프로그램 집합이 전송됩니다.가장 자주 사용하는 백엔드는 GNU 어셈블리 프로그램으로 가스 또는 as라고 부른다.1986년에 발표된 것이지만 여전히 빈번하게 사용되고 있다.
프로그램 집합의 출력은 대상 파일입니다.이것은 링크기에 전달됩니다.
링크 4
컴파일과 조립 과정은 단일 파일에서 실행됩니다.링크기는 헤더 파일과 실행 파일, 외부 라이브러리 등 프로젝트의 모든 부분을 연결하는 데 사용됩니다.만약 함수가 다른 파일에서 extern 또는 유사한 파일로 정의된다면, 링크기의 작업은 함수가 실제 정의되었는지 확인하는 것입니다.수천 줄의 코드가 있는 프로젝트에서 파일의 미세한 변경을 위해 모든 내용을 다시 컴파일하는 것은 큰 고통이 될 것이다.대신 변경 내용이 포함된 파일을 다시 컴파일하고 항목을 다시 연결합니다.
일반적으로 GNU/Linux 시스템에서는 프로그램 ld를 사용합니다.GNU 링크입니다.gcc 프로그램은 개발자의 업무를 더욱 쉽게 하기 위해ld에 대한 호출을 봉인했지만, 필요하면 수동으로 완성할 수 있습니다.
이것은 단지 거대한 GCC 프로젝트의 일별일 뿐이다. 현재 2000만 줄도 안 되는 코드만 있다.기술 문서를 읽으면서 나는 컴파일러의 구조를 대충 이해했다.분석을 한 후에 나는 자신의 컴파일러를 기획하기 시작할 수 있다.
"The C Preprocessor" ↩
"GCC Internals" ↩
"GCC Internals/GCC Architecture - Wikibooks." ↩
"c++ - How does the compilation/linking process work? - Stack Overflow." ↩
Reference
이 문제에 관하여(컴파일러 시리즈 섹션 2: GCC), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/miiizen/compiler-series-part-2-gcc-2mm4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)