-
컴파일러 구조(~후단부)프로그래밍언어론 2023. 3. 11. 16:01
후단부
후단부 에서는 코듯 생성과 코드 개선부로 나뉜다.
코드 생성은 중간코드(AST)로 된 전단부의 결과로 목적코드를 생성한다.
전단부의 결과를 바로 목적 코드 생성에 들어가는 것이 아니고, 먼저 코드 개선 단계를 거친다.
트리 또는 중간 코드 상태에서 의미적으로 중복 또는 불필요한 부분 즉, 간단하게 할 수 있는 코드 등을 찾아서 변환한다.
코드 생성 이후에도 한번더 코드 개선 단계를 거치는데, 이때는 생성된 코드로 목적 기계의 특징에 따른 모든 가능한 개선 방법을 동원한다.좀더 과정을 세밀하게 알아보자.
코드 생성기
코드 생성기에서는 목적 코드를 생성한다.
심볼 테이블을 훑으면서 변수의 주소를 할당한다.- 목적코드란?컴퓨터의 명령문과 운영체제에 따라 정의된 어셈브리 or 기계어
- 비교나 계산 명령문에서 레지스터를 사용
- 다른 곳으로 제어가 이동해야 하는 경우는 jump 사용
코드 생성 단계에서는 심볼테이블 정보를 바탕으로 데이터와 변수 주소를 할당한다.
변수 이름을 사용하는 연산은 레지스터로 load후 계산하는 코드를 생성한다. 이때 저장은 다시 레지스터에서 변수로 다시 저장한다.코드 생성은 단순 패턴매핑에 의해 고급 언어의 문장이나 연산에 대응하는 명령문 여러개를 연속으로 생성한다.
제어 구조(if, for…)는 레이블 생성과 점프로 매칭한다.레지스터를 사용하는 이유는 레지스터에 있는 값은 메모리로 부터 로드할 필요 없이 바로 계산이 가능하기 때문이다.
일반적으로 메모리로 다시 접근해서 load하는 연산은 시간소요가 매우 많이 걸리낟.
메모리 로드 / store횟수가 많아지면 성능이 저하된다.코드 개선
주어진 코드를 동일한 결과를 보장하면서 더 효율적인 동작으로 변환시킨다.
(효율성이란 속도 개선, 메모리 절약을 말한다.)
주어진 코드를 단순히 기계어로 번역하면 성능이 떨어진다.사람이 작성한 코드보다 컴파일러가 작성한 어셈블리 코드가 더 빠른이유는 코드 개선을 위해
컴파일러가 많은 연산을 반복하여 개선가능한 것들을 모두 바꾸기 때문이다.코드 개선 단계는 AST단계, 코드 생성후 기계 독립적개선, 기계종속적 개선단계가 있다.
- 코드 생성전 단계
고급언어의 논리적인 수준에서 생략 가능한 부분과 바꾸어 성능이 더 좋아질 수 있는 계산을 찾는다.
사람이 작성한 코드는 불필요한 코드와 중복부분이 많은데 컴파일러는 이를 모두 찾아서 실행 코드에 포함되지 않도록 제거하거나 바꾼다.공통수식부분: 같은 계산이 반복 -> 임시값으로 레지스터에 저장 후 그대로 사용
불필요한 계산: 쓰이지 않으면 필요없음
연산 변경: *2는 좌측쉬프트, /2는 우측쉬프트
루프불변: 루프 안에서 루프와 상관이 없는 계산이 있으면 부프 밖으로
도달불가: if조건식에서 항상 true이면 else 제거
이 외에도 많은 부분존재- 코드 생성후 기계 독립적 개선
대표적으로 load명령수를 줄인다.
CPU는 레지스터에 있는 값은 1초에 수백만번이 가능하지만, 메모리에 있는 값을 ALU로 계산하는 것은 수십, 수백사이클을 기다려야 한다.
따라서 load수를 줄이는 것이 코드 성능 개선을 위해 핵심적이다.
이는 캐시메모리의
원리와 비슷한데, 생성된 코드를 비교 계산해서 레지스터에 남길 것과 메모리로 보낼
것을 선택한다. 생성된 코드를 앞뒤로(윈도우) 분석하여 곧 다시 쓰일 값은 가능한 한
레지스터에 남기고 그렇지 않은 값은 메모리에 저장(store)하고 그 레지스터를 다른
값에 할당한다.- 코드 생성 후의 기계의존적 코드 개선
특정 기계(CPU 칩)의 명령문 집합의 특징과 계산상 장점을 이용하여 명령문을 바꾸는 것이다.
CPU에 따라 특정 기능을 잘 할 수 있게 하나의 명령문을 만들거나 특수 레지스터를 설계하여 제공한다.728x90'프로그래밍언어론' 카테고리의 다른 글
메모리 영역 (2) 2023.03.20 바인딩 (0) 2023.03.11 컴파일러의 구조(~ 전단부) (0) 2023.03.08 라이브러리와 링크, 그리고 적시컴파일 (0) 2023.03.06 컴파일러와 인터프리터 (0) 2023.03.06