독서/컴파일러 입문

1. 컴파일러 개론

studylida 2025. 4. 16. 20:28

🎯 학습 목표와 중점 사항

이번 슬라이드에서 학습해야 할 내용

  1. 컴파일러란 무엇인가? (정의와 역할)
  2. 컴파일러의 입력과 출력
  3. 컴파일러의 구성 구조(Front-End, Back-End, Intermediate Code)
  4. 언어 종속(Language-dependent) vs 머신 종속(Machine-dependent)

🔍 중점적으로 공부해야 할 것

  • "컴파일러는 어떤 작업을 하는가?" → 언어를 번역하는 자동화 도구라는 큰 그림을 기억할 것.
  • 프론트엔드 vs 백엔드 구분 정확히 이해하기
  • 중간 코드(IC)의 역할과 왜 분리해서 사용하는지
  • 향후 LEX / YACC, IR(Intermediate Representation) 등과 어떻게 연결되는지 상상해볼 것

1️⃣ 번역기와 컴파일러

📌 컴파일러란?

"A compiler is a computer program which translates programs written in a particular high-level programming language into executable code for a specific target computer."

💡 쉽게 풀이하면?

  • 고급 언어(High-level language)기계어(Object code)로 바꿔주는 번역기
  • 예시: C 컴파일러(SPARC용)
    → C 소스 코드를 받아서 SPARC에서 실행 가능한 기계어를 생성

🔁 입력과 출력 흐름

[Source Programs] 
        ↓
    [Compiler]
        ↓
[Object Programs]
  • 입력: C, Java 등 고급언어
  • 출력: 어셈블리 언어, 머신 코드

2️⃣ Compiler Structure

📌 구성요소: Front-End / Intermediate Code / Back-End

[Source Program]
        ↓
   ┌───────────────┐
   │  Front-End     │    ← 언어 종속(Language Dependent)
   │      ↓         │
   │ Intermediate   │
   │     Code       │    ← 언어와 머신 사이의 중간 단계
   │      ↓         │
   │  Back-End      │    ← 머신 종속(Machine Dependent)
   └───────────────┘
        ↓
[Object Program]

🔍 구성요소 설명

구분 설명 특징
Front-End - 소스 코드 분석 (어휘 분석, 구문 분석, 의미 분석)
- 중간 코드 생성
언어에 종속
Intermediate Code (IC) - 플랫폼 독립적인 중간 표현
- 다양한 백엔드와 조합 가능
중간 표현이라 재사용 가능
Back-End - IC를 기반으로 최적화 및 기계어 코드 생성 기계에 종속

🧠 포인트 기억하기

  • 같은 프론트엔드 + 다른 백엔드 = 여러 플랫폼으로 확장 가능
    (예: C 컴파일러를 ARM에도, x86에도 쓰고 싶을 때!)

✅ 공부 팁 요약

학습 포인트 기억해야 할 것
컴파일러란? 고급 언어 → 기계어로 바꾸는 번역기
입력-출력 구조 Source → Compiler → Object
구조 분리 이유 언어와 머신을 각각 독립적으로 다루기 위함
IC의 역할 재사용성과 확장성을 위한 중간 표현
Front vs Back Front는 "언어 중심", Back은 "기계 중심"

개념 핵심 키워드 반드시 이해해야 할 것
Cross Compiler 타겟 머신 다름 컴파일 위치와 실행 위치가 다른 경우
Interpreter 실행 즉시 변환 번역 없이 바로 실행. 결과 즉시 출력
Preprocessor 전처리 컴파일 전 텍스트 수준 변환 수행

1️⃣ Cross Compiler (교차 컴파일러)

✅ 정의

"A cross-compiler is a program which is to run on machine A and produce target code for another machine B."

  • 실행 환경과 목적 코드의 플랫폼이 다름
    • 즉, 컴파일은 A 컴퓨터에서, 생성된 코드는 B 컴퓨터에서 실행

✅ 예시

  • 스마트폰용 프로그램을 PC에서 컴파일 → 스마트폰에서 실행
  • 임베디드 시스템 개발 시 자주 사용

✅ 구조 요약

[Source Program]
      ↓
[Compiler on A machine]
      ↓
[Target Code for machine B]

🔍 특징

  • Front-End: 언어 종속
  • Back-End: 기계(B 시스템) 종속

📌 용도

  • downloading: 생성된 바이너리 파일을 B에 넣고 실행
  • bootstrapping: 새로운 플랫폼용 컴파일러를 그 플랫폼에서 실행하기 위해 미리 만들어 놓는 기술

2️⃣ Interpreter (인터프리터)

✅ 정의

"An interpreter transforms a program directly into a sequence of machine actions and produces the results of the program."

  • 기계어로 완전한 번역 없이 → 바로 실행

✅ 구조 요약

[Source Program]
      ↓
[Interpreter]
   ↓       ↓
실행    결과 출력

🔍 특징

  • 프로그램 전체를 번역하지 않고 한 줄씩 실행
  • 대표 언어: Python, JavaScript
  • 컴파일러에 비해 느리지만, 디버깅과 교육용에 적합

📌 용도 비교

항목 Compiler Interpreter
목적 실제 운영 시스템 교육, 개발, 실험
처리 방식 전체 번역 후 실행 즉시 실행
출력물 Object 코드 생성 없음 (바로 실행됨)

3️⃣ Preprocessor (전처리기)

✅ 정의

컴파일 전에 소스코드를 가공(확장)하여 컴파일러에 전달

✅ 구조 요약

[Source Program]
      ↓
[Preprocessor]
      ↓
[Extended Source Program]
      ↓
[Translator or Compiler]
      ↓
[Target Code]

🔍 주요 기능

  • 매크로 치환: #define
  • 조건부 컴파일: #ifdef, #ifndef
  • 파일 포함: #include

✅ 대표 언어

  • C 언어는 전처리기를 강하게 사용하는 대표적인 언어

✅ 학습 정리 요약

구분 설명 핵심 포인트
Cross Compiler 실행 환경 ≠ 실행 대상 타겟 플랫폼용 코드 생성
Interpreter 바로 실행 교육, 실험, 디버깅에 적합
Preprocessor 컴파일 전 텍스트 조작 조건부 컴파일, 매크로 처리

구분 개념 학습 포인트
1 컴파일러 전체 구조 Front-End vs Back-End 구분, 각 단계의 역할
2 Lexical Analyzer (어휘 분석기) 토큰 생성, 정규 표현식 기반
3 Syntax Analyzer (구문 분석기) 문장 구조 분석, 구문 트리(파스트리) 생성

1️⃣ 컴파일러 구조 (General Compiler Structure)

📌 전체 흐름

[Source Code]
  ↓
Lexical Analyzer     ⇒ Token
  ↓
Syntax Analyzer      ⇒ Parse Tree
  ↓
Intermediate Code Generator  ⇒ IR
  ↓
Code Optimizer       ⇒ Optimized IR
  ↓
Target Code Generator ⇒ Object Code

✅ 주요 단계 요약

영역 구성 요소 주요 역할 종속성
Front-End Lexical, Syntax, Intermediate - 문법 오류 탐지
- 중간 코드 생성
언어 종속
Back-End Optimizer, Target Code Gen. - 최적화
- 기계어 변환
하드웨어 종속

2️⃣ Lexical Analyzer (어휘 분석기 / 스캐너)

✅ 역할

  • Source Code → Token들의 시퀀스로 분리
  • 각 토큰은 정수값 등으로 인코딩되어 내부에서 다루기 쉽게 됨

🔍 구성 흐름

소스 코드 if (a > 10)
     ↓
토큰:     if   (   a   >   10   )
번호:    32   7   4  25   5   8

🧠 기억할 포인트

  • 정규 표현식을 기반으로 구성
  • 토큰 단위로 의미를 부여 (키워드, 식별자, 상수, 기호 등)
  • 자동화 도구: LEX로 생성 가능

3️⃣ Syntax Analyzer (구문 분석기 / 파서)

✅ 역할

  • 토큰들의 나열 → 문법 구조로 해석
  • 구문 오류를 탐지하거나, 구문 트리(Parse Tree) 생성

🔍 출력 구조

ex) if (a > 10) a = 1;
       ↓
          if
         /  \
       >     =
     / \     / \
    a  10   a  1

🧠 기억할 포인트

  • 문법(Grammar)을 기반으로 파싱 수행
  • 출력 형태: Parse Tree, Abstract Syntax Tree(AST)
  • 자동화 도구: YACC로 생성 가능
  • 구문 분석은 형식 언어 이론과 직결 (CFG 기반)

✅ 학습 요약 포인트

항목 키워드 핵심 정리
컴파일러 구조 Front-End / Back-End 언어 종속과 기계 종속으로 나뉨
어휘 분석기 Token, 정규 표현식, LEX 문자열 → 단어로 분리
구문 분석기 Parse Tree, 문맥 자유 문법(CFG), YACC 문장 구조 분석 및 트리 생성

파트 학습 핵심
Intermediate Code Generator 트리 기반 의미 분석, U-code 생성 원리
Code Optimizer 최적화 목적과 기법 구분 (Local/Global)
Target Code Generator 기계어 생성 과정, 레지스터/메모리 관리
Error Recovery 오류의 종류와 대응 전략 (Recovery vs Repair)

3️⃣ Intermediate Code Generator

✅ 핵심 역할

  • Semantic Analysis 포함: 타입 검사(Type Checking)
  • 파싱 트리를 DFS(깊이 우선 탐색) 방식으로 읽고 중간 코드 생성
  • 변수 주소 참조 방식: (base, offset) 형태

🔍 예시 해석

a = b + 1;
⇒ 트리 구조:
        =
       / \
      a   +
         / \
        b   1

⇒ U-Code 생성:
lod 1 2   ← b의 값 로드 (base=1, offset=2)
ldc 1     ← 상수 1
add       ← 더하기
str 1 1   ← 결과를 a에 저장 (base=1, offset=1)

🧠 핵심 포인트

  • 중간 코드는 플랫폼 독립적인 표현
  • 향후 백엔드와 분리 가능한 핵심 자료

4️⃣ Code Optimizer

✅ 의미

  • 선택적(optional) 단계지만, 실행 시간/공간 최적화 목적
  • 주 목표:
    • 실행 시간 단축
    • 코드 크기 감소

✅ 최적화 기준

  • 프로그램 의미 보존
  • 평균 실행 속도 향상
  • 최적화에 쓴 비용보다 이득이 클 것

✅ 최적화 기법

📌 Local Optimization
  • 한 basic block 내에서 수행 (제어 흐름 없음)
  • 대표 기법:
    1. Constant folding: 2 + 35
    2. Redundant load/store 제거
    3. Algebraic simplification: x * 1x
    4. Strength reduction: x * 2x + x
📌 Global Optimization
  • 제어 흐름을 포함한 전체 범위에서 수행
  • 대표 기법:
    1. Common subexpression 제거
    2. Loop invariant 이동
    3. Unreachable code 제거

5️⃣ Target Code Generator

✅ 역할

  • 중간 코드(IC 또는 최적화된 IC) → 기계어(Target Code)로 변환

✅ 주요 작업

  1. 명령어 선택 및 생성 (Instruction selection)
  2. 레지스터 관리
  3. 스토리지 할당 (변수 위치)
  4. 기계 종속적 최적화 수행

🧠 대표 도구

  • LLVM: 백엔드 코드 자동 생성 도구

6️⃣ Error Recovery

✅ 개념

용어 의미
Error recovery 에러가 다음 문장에 영향을 주지 않도록 복구
Error repair 에러가 생겼을 때 직접 수정 시도

✅ Error 처리 구성 요소

  • Detection (감지)
  • Recovery (복구)
  • Reporting (보고)
  • Repair (수정)

✅ 에러의 종류

종류 예시
Syntax Error 괄호 누락, 문장 종료 누락 등
Semantic Error 타입 불일치, 정의되지 않은 변수 등
Run-time Error 0으로 나누기, 포인터 오류 등

✅ 전체 흐름 요약

단계 주요 작업 핵심 키워드
Intermediate Code Generator 의미 분석 + 중간 코드 트리 기반, (base, offset)
Code Optimizer 코드 효율 향상 Local vs Global, 의미 보존
Target Code Generator 기계어 생성 명령어 선택, 레지스터
Error Recovery 오류 감지 및 복구 Recovery vs Repair, Syntax/Semantic

🎯 학습 목표 및 중점 사항

주제 학습 포인트
컴파일러 자동화 도구의 필요성 왜 compiler-compiler가 필요한가?
주요 도구 종류 LEX, YACC, PGS, 자동 코드 생성기
입력/출력 구조 각 도구의 입력 자료 구조와 출력 산출물 이해
생성 대상 어휘 분석기, 구문 분석기, 타겟 코드 생성기
용어/형식 정규표현식, BNF/EBNF, AST 등과 연계 이해

1️⃣ 컴파일러 자동화 도구의 필요성

✅ 문제 상황

  • N개의 언어 × M개의 머신 환경 → N × M개의 컴파일러 필요
  • 수작업으로 만들기에는 확장성, 유지보수 측면에서 한계

✅ 해결책

  • Compiler Generating Tool (Compiler-Compiler) 도입
    • 입력: 언어 기술서 + 머신 기술서
    • 출력: 해당 언어를 해당 머신에서 실행 가능한 컴파일러

2️⃣ Compiler-Compiler 모델

✅ 구성

[Language Description] + [Machine Description]
                ↓
         Compiler-Compiler
                ↓
     [해당 언어 → 해당 머신용 Compiler 생성]

✅ 사용 이론 및 도구

  • Language: 문법 이론 (Grammar, CFG, BNF/EBNF)
  • Machine: HDL, ISP, ISPS 등
  • 대표 예시: YACC, LEX, PGS, LLVM

3️⃣ LEX (Lexical Analyzer Generator)

✅ 개요

  • 정규표현식 기반 어휘 분석기 자동 생성 도구
  • 입력: Regular Expression + Action Code
  • 출력: Token Stream을 출력하는 lex.yy.c

✅ 작동 구조

[정규표현식 + 액션] 
       ↓
      LEX
       ↓
   Lexical Analyzer (.c 파일)
       ↓
   Token Stream 생성

4️⃣ PGS (Parser Generator System)

✅ 개요

  • CFG(문맥 자유 문법) 기반 구문 분석기 자동 생성
  • Grammar → Parsing Table → Parser

📌 예시 시스템

이름 작성자 특징
Stanford PGS John Hennessy AST 생성 중심
Wisconsin PGS C.N. Fisher Error Recovery 기능 강조
YACC UNIX 환경, C 기반 LEX와 연계 사용, Action Code 포함 가능

5️⃣ YACC (Yet Another Compiler Compiler)

✅ 구성 흐름

[정규표현식 + Action] → LEX  → lex.yy.c (어휘 분석)
[문법 규칙 + Action] → YACC → y.tab.c (구문 분석)
lex.yy.c + y.tab.c → 실행 결과 생성
  • LEX와 연동하여 전체 분석기 구축 가능
  • UNIX 환경에서 실무용으로 가장 널리 쓰임

6️⃣ 자동 코드 생성기 (Automatic Code Generator)

✅ 역할

  • 중간 코드(IC)기계어(Target Code) 자동 생성

✅ 구성

[Machine Description + Pattern] 
            ↓
  Code Generator Generator
            ↓
        [Table 생성]
            ↓
      Code Generator 실행
            ↓
       Target Code 생성

✅ 핵심 구성 요소

  • Table-Driven 방식: 각 명령어 생성 패턴 정의
  • Driver Routine: 생성 테이블을 활용해 실제 코드 생성
  • 도구 예시: CGA (Code Generating Algorithm)

✅ 전체 요약표

도구 생성 대상 기반 이론 특징
LEX Lexical Analyzer 정규표현식 토큰 추출, lex.yy.c 생성
YACC Syntax Analyzer 문맥 자유 문법 (CFG) 파싱 테이블 및 트리, y.tab.c
PGS Parser Generator CFG, AST 스탠포드/위스콘신 등 버전 존재
Code Generator Generator Target Code Generator 패턴 매칭, Table 기반 백엔드 자동화 목적

📌 학습 팁

  • LEX는 정규 표현식과 직접적으로 연결, Regular Language 기반
  • YACC는 문맥 자유 문법(CFG) 기반, 파싱 알고리즘 학습과 연계
  • 자동 생성기의 목적은 결국 확장성과 유지보수성 향상
  • 이후 LLVM 같은 현대 시스템이 이 구조를 얼마나 발전시켰는지 비교하면 좋음

🎯 학습 목표 및 중점 사항

학습 포인트 핵심 내용
PQCC와 ACK의 구조 차이 어떤 식으로 자동화를 구현했는가
중간 표현 방식 TCOL(PQCC), EM(ACK) 구조 이해
자동화 방식 Table-driven code generation, Abstract machine 기반
활용 배경 다양한 언어/머신 조합 대응을 위한 확장성
공통점 vs 차이점 공통 목표(컴파일러 자동화) + 구현 철학의 차이

1️⃣ PQCC (Production Quality Compiler Compiler)

✅ 개요

  • W.A. Wulf (Carnegie-Mellon Univ.)
  • 입력: 언어 기술(Language Description) + 머신 기술(Machine Description)
  • 출력: PQC + Table → 최종 Object Code 생성

✅ 구조 (슬라이드 Page 28)

[Source Program]
      ↓
  Front-End         → TCOL 생성
      ↓
     PQC + Table ← PQCC에서 생성
      ↓
[Object Code]

✅ 핵심 요소

  • TCOL (Tree Code Object Language): 트리 기반 중간 표현, 문법+의미 정보 포함
  • Pattern Matching 기반으로 코드 생성
  • TCOL 순회 방식으로 타겟 코드 생성 (트리 워킹 기반)

2️⃣ ACK (Amsterdam Compiler Kit)

✅ 개요

  • Andrew Tanenbaum (Vrije 대학)
  • Front-End와 Back-End를 분리하고, EM이라는 추상 기계어(Abstract Machine Code)를 중간 표현으로 사용

✅ 구조 (슬라이드 Page 29)

[Source Program] (e.g. FORTRAN, PASCAL, C, ...)
        ↓
      Front-End
        ↓ EM (중간 코드)
      Back-End → [Object Code] (Intel, Motorola, Zilog, SPARC 등)
                       ↓
                 [Interpreter] → 실행 결과

✅ 특징

  • UNCOL(Universal Intermediate Language) 개념 기반
  • Portable Compiler 제작에 유리
  • EM 코드는 필요 시 해석기로 실행 가능

✅ PQCC vs ACK 비교표

항목 PQCC ACK
설계자 W.A. Wulf Andrew Tanenbaum
중간 표현 TCOL (트리 기반) EM (Abstract Machine Code)
구조 Table 기반 자동 생성기 UNCOL 철학 기반 추상 머신
강점 정밀한 패턴 매칭, table 기반 생성 최적화 이식성(portability), 다양한 기계 대응
실행 방식 코드 생성 중심 해석기 통한 실행도 가능

🧠 학습 팁

  • TCOL = 트리 구조 기반 표현 → 파싱 트리 기반의 연산 최적화에 강함
  • EM = 추상 머신 코드 → 다양한 실제 머신으로의 매핑 유연
  • 둘 다 결국 N개의 언어 × M개의 머신을 효과적으로 커버하려는 자동화 시도
  • 현대의 LLVM이 이 철학을 잇는 현대 시스템 중 하나!

'독서 > 컴파일러 입문' 카테고리의 다른 글

2. 형식 언어  (0) 2025.04.17