[Compiler Design] Run-Time Storage Management
IR 생성의 예시로 WebAssembly가 있다.
C/C++/Rust 언어를 컴파일해서 .wasm 바이너리를 생성하고, 브라우저의 자바스크립트 엔진과 연동해서 실행한다.
내부적으로는 스택 머신 기반의 IR을 사용함.
브라우저에서 고사양 작업을 수행할 수 있음.

운영체제에서 메모리 영역 다룰때랑 똑같다.
Code/Data 영역은 하위 주소에 위치
Stack은 높은 주소에서 낮은 주소로 자라남
Heap은 낮은 주소에서 높은 주소로 자라남.
WASM 에서도 메모리 경계를 넘어서 데이터를 쓸 수 있다. - StackOverFlow
사람이 읽기 쉬운 High Level IR을 기계가 읽기 쉬운 Low Level IR로 변환해보자.
일단 단계별로 쪼개는 Divide-and-Conquer 적인 마인드가 중요함.

t = [[e1 OP e2]]
1. e1 계산하고 t1에 저장
2. e2 계산하고 t2에 저장
3. t1과 t2 연산하고 t에 저장
t1 = [[OP e1]]
1. t1 = [[e1]]
2. t = OP t1
(프언개에서 한거랑 똑같음;)
계산 두 개 봤으니 알겠지만 나머지 계산도 다 거기서 거기임
t = [[v[e]]]
여기서 v는 array[T], S는 데이터 크기
1. t1 = addr v
2. t2 = [[e]]
3. t3 = t2 * S
4. t4 = t1 + t3
t = [t4]
시작 주소 저장 / 인덱스 계산 / 오프셋 계산 / 최종 주소
하나하나 다 적고 있는건 좀 그렇고.. 변환 별로 핵심만.
1. 논리 연산은 앞의 조건이 참이면 뒤의 조건을 실행하지 않으니 jump 명령어로 구현한다.
2. 변수에 값을 넣을 때는 주소를 계산해서 해당 주소가 가리키는 메모리에 값을 쓴다.
3. if와 while은 jump와 label으로 변환한다. 핵심은 조건을 뒤집어서 점프.
4. switch는 if-else if 로 순차 비교도 되고 jump table 만들고 인덱스로 바로 점프할 때도 있음.
5. 함수 호출은 인자를 먼저 계산하고 call 실행 (프언개)
6. 모든 식에 임시 변수를 적용하면 힘들어진다. 피연산자가 이미 변수거나 상수면 바로 사용.
변환 파트는 프언개랑 너무 똑같음
프로그램이 실행될 때 메모리는 크게 네 가지 영역으로 구분된다.
사실 운영체제에서 다 했음.
Code - 기계어 명령어가 Read-Only 상태로 저장된다.
Static Data - 전역 변수 및 정적 변수가 저장된다.
Heap - malloc, new 명령어로 동적으로 할당되는 메모리.
Stack - 함수 호출 시 생성되는 지역변수, 인자, 반환 주소를 저장한다.
int a; // 전역 변수 -> Static Data (Memory)
void foo(int b, double c) { // 매개 변수 -> Stack (또는 Register)
int d; // 지역 변수 -> Stack
struct { int e; char f; } g; // 구조체(복합 타입) -> Stack (Memory)
int h[10]; // 배열 -> Stack (Memory)
static char i = 5; // static 지역 변수 -> Static Data (Memory)
float j; // 지역 변수 -> Register (가상 레지스터)
}
코드를 보고 변수가 어디에 저장되는지 구분할 수 있어야 함..
static이 붙으면 지역 변수 위치에 선언되더라도 Static Data 영역에 저장되고, 프로그램이 끝날 때 까지 유지된다.
함수가 호출 될 때 마다 스택에 Stack Frame이 하나씩 쌓인다.
스택 프레임워 구성 요소는 운영체제에서 다 했던거니까 패스..
컴파일러는 함수 호출을 만나면 단순히 점프만 하는게 아니라 여러 부가 작업을 수행한다.
호출 전에 인자를 스택에 넣어준다. - push arg2, push arg1
함수 수행을 마치고 복귀할 주소를 저장한다. - Return Address를 스택에 push
함수가 실행되자마자 Prologue가 실행된다.
Old FP 저장, 새 FP 설정, 공간 확보 - push fp | fp = sp | sp = sp - size
함수가 종료될 때는 Epilogue가 실행된다.
SP 복구, Old FP 복구, 리턴 - sp = fp | pop fp | ret
SSS 에서 BOF 할 때 Offset을 계산하는 원리와 똑같음.
FP를 기준점으로 두고 위 / 아래로 접근한다.
그냥 리버싱 문제
'Computer Science > Compiler Design' 카테고리의 다른 글
| [Compiler Design] Machine Dependent Processing (0) | 2025.11.30 |
|---|---|
| [Compiler Design] Semantic Analysis (0) | 2025.11.25 |
| [Compiler Design] Intermediate Representation (0) | 2025.11.24 |
| [Compiler Design] SDD / AST (0) | 2025.11.17 |
| [Compiler Design] LR(0) / SLR / LR(1) / LALR (0) | 2025.11.03 |
댓글
이 글 공유하기
다른 글
-
[Compiler Design] Machine Dependent Processing
[Compiler Design] Machine Dependent Processing
2025.11.30 -
[Compiler Design] Semantic Analysis
[Compiler Design] Semantic Analysis
2025.11.25 -
[Compiler Design] Intermediate Representation
[Compiler Design] Intermediate Representation
2025.11.24 -
[Compiler Design] SDD / AST
[Compiler Design] SDD / AST
2025.11.17