프로그램과 실행 3: 컴파일러 추가내용

 <컴파일러의 사용 효과>

컴파일러를 사용한 결과로 다음 조건들을 만족해야한다.

1. 변환 과정에서 프로그램의 뜻을 보존
2. 실용적인 면에서, 입력으로 들어온 프로그램을 어떤 면에서든지 개선.
(어셈블리어를 기계어로 변환하는 경우 기계어가 해석할 수 있게 된다는 이점)
(같은 언어로 옮긴 경우에는 성능이 개선되는 등의 이점이 존재해야함.)

위 두 가지를 만족하지 않는다면 굳이 컴파일러를 쓸 이유가 없다.


<컴파일 과정>

컴파일러나 프로그래밍 언어의 특성에 따라
일부 단계는 생략되거나 더 세부적인 단계로 나뉠 수도 있다.

일반적인 과정은 다음과 같다.

구문 분석

소스 코드 파일을 읽어 개별 문법요소(연산자, 괄호, 식별자 등) 단위로 자른후,
이 문법요소들을 해석하여 추상 구문 트리를 생성한다.
이 과정에서 문법에 맞지 않는 소스 코드는 사용자에게 알려준다.

최적화

추상 구문 트리를 분석하여 최적화를 수행한다.
도달할 수 없는 코드를 식별하거나,
상수 표현식을 미리 계산해 두거나,
루프 풀기 등의 대부분의 최적화가 이 단계에서 수행된다.

코드 생성

최적화된 구문 트리로부터 목적 코드를 생성한다.
목표 언어가 기계어일 경우, 레지스터 할당, 연산 순서 바꾸기
하드웨어에 맞는 최적화가 이 단계에서 수행된다.
대부분의 하드웨어 최적화 알고리즘은 NP 복잡도를 갖지만,
휴리스틱을 통해 많은 최적화가 수행된다.

링킹

목적 코드가 기계어일 경우,
여러 라이브러리 목적 코드를 묶어 하나의 실행 파일을 생성하게 된다.
이 과정은 링커에 의해 수행되며,
어떤 사람들은 링커를 컴파일러의 일부로 간주하지 않기도 한다.


<일단 구조와 다단 구조>


일단 구조
원시 코드 -> READ -> 번역 -> 목적 코드

다단 구조
원시 코드 -> READ -> 번역 -> 중간 코드1 -> ... -> 목적 코드


다단 구조에서 중간코드의 효용
1. 다양한 언어 지원 
다양한 입력 언어를 동일한 중간 표현으로 표현하거나
동일한 중간 표현을 여러 가지 출력 언어로 표현하면
다양한 입력 언어와 출력 언어를 지원하는 컴파일러를 작성할 수 있다.
✔️ 다중언어, 다중대상 컴파일

2. 속도 및 최적화
고수준 언어일수록 성능보다는 사람에게 이해하기 쉬운 형태를 염두에 두고 설계된다.
때문에 중간형태를 거치는 것이
저수준에서 효율적으로 프로그램을 최적화한 다음
최종적으로 출력물을 내놓는 데 유리할 수 있다.

✔️ (고수준언어 -> 기계어)로 한 번에 바꾸는 것보다
✔️ (고수준언어 -> IR -> 기계어) 과정을 거치는 것이 유리할 수 있음.

3. JIT 컴파일
스몰토크, 자바, 마이크로소프트 공통 중간 언어(CIL) 등의 컴파일러는
가상 머신의 바이트코드를 출력한다. 
그러나 가상 머신은 플랫폼의 기계어에 비해 속도가 느릴 수밖에 없으므로
가상 머신에는 저스트 인 타임 컴파일러가 탑재되어
실행 직전에 현재 플랫폼의 기계어로 다시 한 번 컴파일되어 속도를 향상시킨다.
✔️ JVM


< 네이티브 컴파일러 대 크로스 컴파일러 >

컴파일러가 실행되는 컴퓨터나 운영체제가
컴파일러의 목적코드가 실행될 컴퓨터나 운영체제와 같은 경우
네이티브 컴파일러(native compiler 또는 hosted compiler)라고 한다.

크로스 컴파일러(cross compiler)는
다른 컴퓨터나 운영체제에서 실행되도록 제작된다.
임베디드 시스템 등
소프트웨어 개발에 충분한 환경을 갖추지 못한 환경에서 동작할 프로그램을
만들기 위해 사용된다.



네이티브 컴파일러 예

x86 기반 프로세서 - 윈도우OS 위의 컴파일러가

x86 기반 프로세서 - 윈도우OS 위에서 실행될 목적코드 생성 할 때,

이 컴파일러는 네이티브 컴파일러이다.


마이크로소프트 윈도우용 응용 프로그램 개발.
비주얼 스튜디오로 컴파일하면 실행파일(exe 파일)을 생성한다.
( 비주얼 스튜디오 : MS에서 만든 IDE )


리눅스용 응용 프로그램을 개발하기 위해 
x86용 gcc를 사용하면 리눅스 실행파일이 생성된다.


크로스 컴파일러 예


리눅스(x86)에서 ARM용 임베디드 시스템용 프로그램이나 커널을 개발하기 위해 
ARM용 gcc을 사용하면 ARM 코드의 실행파일이 생성된다.

[컴파일러의 환경]
x86 아키텍쳐의 하드웨어 + 리눅스 OS

[컴파일러]
( x86 - 리눅스 OS ) 위에서 실행되는 ARM용 gcc

[목적코드의 환경]
ARM 아키텍쳐의 하드웨어

[목적코드]
ARM 아키텍쳐의 하드웨어 위에서 실행되는 임베디드 시스템 프로그램 OR 커널.


마이크로소프트 윈도에서 
8051, AVR, PIC등의 시스템 프로그램을 개발하기 위해
해당 컴파일러를 사용하면 해당 CPU의 코드가 생성된다.

자바
가상 머신에서 동작할 프로그램을 만드는 컴파일러도 있다.
이 경우 일반적으로 출력물이 가상 머신을 위해 제작된 바이트코드 형태의 기계어가 되므로 바이트코드 컴파일러라고 부른다.





댓글

이 블로그의 인기 게시물

실무진 면접 경험으로 정리하는 백엔드 (1) : 에듀 테크 기업 면접

노마드코더 개발자북클럽 Clean code 완주, 독후감

Blogger 커스터마이징 : CSS 수정 (sticky-header)