컴파일러

컴파일러(Compiler)는 특정한 형식으로 작성된 프로그램을 의미가 대응되는 다른 형식의 프로그램으로 변환하는 소프트웨어이다. 일반적으로 프로그래밍 언어로 작성된 소스 코드를 기계어, 목적 코드, 바이트코드 또는 다른 프로그래밍 언어로 변환한다. 이 과정을 컴파일(Compilation...

분류시스템 소프트웨어, 프로그래밍 언어 구현
입력소스 코드, 중간 표현
출력기계어, 목적 코드, 바이트코드, 다른 프로그래밍 언어
주요 구성프런트엔드, 중간 표현, 최적화기, 백엔드
관련 기술어셈블러, 링커, 로더, 인터프리터, 가상 머신
대표 구현체GCC, LLVM, Clang, javac, rustc

컴파일러(Compiler)는 특정한 형식으로 작성된 프로그램을 의미가 대응되는 다른 형식의 프로그램으로 변환하는 소프트웨어이다. 일반적으로 프로그래밍 언어로 작성된 소스 코드기계어, 목적 코드, 바이트코드 또는 다른 프로그래밍 언어로 변환한다. 이 과정을 컴파일(Compilation)이라고 한다.

컴파일러는 단순히 명령어의 표기를 바꾸는 변환기가 아니다. 입력 프로그램의 구조를 분석하고, 이름과 타입의 사용이 언어 규칙에 맞는지 검사하며, 프로그램의 의미를 보존하는 중간 표현을 만든 뒤 이를 분석하고 변환한다. 이후 대상 명령어 집합 아키텍처가상 머신이 실행할 수 있는 코드를 생성한다.

전형적인 컴파일러는 어휘 분석과 구문 분석을 수행하는 프런트엔드, 프로그램을 언어와 하드웨어로부터 부분적으로 분리해 표현하는 중간 표현, 코드를 개선하는 최적화 단계, 대상 시스템의 명령어와 호출 규약에 맞는 코드를 생성하는 백엔드로 구성된다. 그러나 모든 컴파일러가 이 구분을 동일하게 따르는 것은 아니다. 작은 컴파일러는 여러 단계를 하나로 통합할 수 있고, 대규모 컴파일러 기반은 프런트엔드와 최적화기, 코드 생성기를 독립된 구성 요소로 제공할 수 있다.[1]

컴파일 결과가 항상 독립적인 실행 파일인 것은 아니다. Java 컴파일러인 javac는 Java 소스 코드를 JVM에서 실행되는 클래스 파일로 변환하며, 다른 컴파일러는 웹 브라우저나 언어 런타임에서 실행되는 바이트코드를 생성할 수 있다.[2] 한 프로그래밍 언어를 다른 고수준 언어로 변환하는 소스 대 소스 컴파일러도 있으며, 프로그램 실행 중 필요한 부분을 컴파일하는 JIT 컴파일과 실행 전에 전체 또는 일부를 변환하는 AOT 컴파일도 사용된다.

현대의 컴파일러는 언어 구현뿐 아니라 정적 분석, 프로그램 최적화, 코드 계측, 디버깅 정보 생성, 자동 완성, 리팩터링과 같은 개발 도구의 기반으로도 활용된다. LLVM과 같은 컴파일러 기반은 여러 언어의 프런트엔드와 여러 하드웨어의 백엔드가 중간 표현을 중심으로 기능을 공유할 수 있도록 구성된다. LLVM IR은 정적 단일 할당 형식에 기반한 공통 코드 표현으로 사용된다.[3]

컴파일러는 보통 어셈블러, 링커, 로더, 표준 라이브러리, 런타임 시스템, 디버거와 함께 하나의 도구 체인을 구성한다. 컴파일러 드라이버는 이러한 프로그램을 순서대로 호출하여 소스 파일에서 실행 파일이나 라이브러리를 만드는 전체 빌드 과정을 조정하기도 한다. 따라서 일상적으로 “컴파일러”라고 부르는 명령은 실제 언어 변환기뿐 아니라 전처리, 어셈블, 링크 단계를 제어하는 드라이버를 의미할 수 있다.

역사

컴파일러 이전의 프로그래밍

초기 자동 코딩 시스템

최초의 컴파일러

FORTRAN과 고수준 언어의 확산

구조적 언어와 컴파일러 이론의 발전

최적화 컴파일러의 등장

휴대 가능한 컴파일러와 UNIX

가상 머신과 관리형 언어

현대 컴파일러 기반

기본 구조

컴파일 과정

프런트엔드

중간 표현

미들엔드와 최적화기

백엔드

컴파일러 드라이버

어휘 분석

문자 스트림과 토큰

정규 언어와 유한 오토마톤

어휘 분석기의 구현

공백과 주석

오류 처리

구문 분석

문법과 파스 트리

추상 구문 트리

하향식 구문 분석

상향식 구문 분석

모호성과 우선순위

구문 오류 복구

의미 분석

이름 해석

심볼 테이블

스코프와 바인딩

타입 검사

오버로드 해석

제네릭과 타입 추론

정적 의미 오류

중간 표현

중간 표현의 목적

트리 기반 표현

선형 중간 표현

제어 흐름 그래프

정적 단일 할당 형식

고수준·중수준·저수준 중간 표현

다단계 중간 표현

프로그램 분석

제어 흐름 분석

데이터 흐름 분석

별칭 분석

포인터 분석

호출 그래프

탈출 분석

의존성 분석

최적화

최적화의 목적

지역 최적화

전역 최적화

루프 최적화

함수 간 최적화

인라이닝

상수 전파와 상수 접기

공통 부분식 제거

죽은 코드 제거

자동 벡터화

프로파일 기반 최적화

링크 시간 최적화

최적화와 프로그램 의미

코드 생성

명령어 선택

레지스터 할당

명령어 스케줄링

스택 프레임

함수 호출 규약

데이터 배치와 정렬

대상별 코드 생성

디버깅 정보와 예외 처리 정보

런타임과 실행 모델

네이티브 코드

바이트코드

가상 머신

런타임 라이브러리

메모리 관리와 가비지 컬렉션

예외 처리

동적 디스패치

외부 함수 인터페이스

컴파일 방식

사전 컴파일

JIT 컴파일

계층형 컴파일

증분 컴파일

병렬 컴파일

분산 컴파일

교차 컴파일

소스 대 소스 컴파일

부분 평가와 특수화

오류 진단

오류와 경고

소스 위치 추적

진단 메시지

오류 복구

수정 제안

언어 서버와 편집기 통합

도구 체인

전처리기

어셈블러

링커

로더

빌드 시스템

디버거

프로파일러

정적 분석기

컴파일러의 종류

단일 패스와 다중 패스 컴파일러

네이티브 컴파일러

교차 컴파일러

바이트코드 컴파일러

JIT 컴파일러

소스 대 소스 컴파일러

역컴파일러

도메인 특화 컴파일러

컴파일러 구현

부트스트래핑

셀프 호스팅

컴파일러 컴파일러

손으로 작성한 프런트엔드

재사용 가능한 컴파일러 기반

테스트와 검증

재현 가능한 빌드

대표적인 컴파일러와 기반

GCC

LLVM

Clang

Microsoft C/C++ Compiler

javac

.NET 컴파일러 플랫폼

rustc

Go 컴파일러

WebAssembly 도구 체인

프로그래밍 언어와의 관계

언어 사양과 컴파일러 구현

구현 정의 동작

컴파일러 확장

언어 기능과 최적화 가능성

타입 체계와 코드 생성

메모리 모델

정의되지 않은 동작

활용 분야

응용 소프트웨어

운영체제와 시스템 소프트웨어

임베디드 시스템

웹과 WebAssembly

그래픽스와 셰이더

데이터베이스와 질의 처리

머신러닝 컴파일러

하드웨어 합성

정적 분석과 개발 도구

정확성·성능·보안

컴파일러 정확성

잘못된 컴파일

형식 검증

신뢰 컴퓨팅 기반

공급망과 빌드 보안

컴파일러 최적화와 보안

장점과 한계

관련 문서

  1. LLVM Project
  2. Oracle Java SE: The javac Command
  3. LLVM Language Reference Manual