Whale IR 참조

타입, 식별자, 함수의 유효성, 평가 순서와 교환 형식을 설명합니다.

Wave Foundation

모듈과 식별자

모듈은 타깃 정보, 전역 정의, 함수로 구성됩니다. 값에는 명시적인 타입이 있습니다. 프런트엔드는 소스 언어의 이름·타입·오버로드·제네릭을 해결한 뒤 typed IR을 생성합니다.

함수와 전역 변수는 서로 다른 내부 이름 공간을 사용합니다. 따라서 함수와 변수가 같은 이름을 가질 수 있습니다. 내부 식별자는 외부 연결 이름인 link_name과 구별되며, 외부 이름은 프런트엔드가 명시합니다. Whale은 새로운 이름을 자동 생성해 외부 충돌을 해결하지 않습니다. 심볼과 링크를 참고하세요.

각 값 정의는 식별자를 갖습니다. 정의는 중복될 수 없고, 타입 메타데이터는 정의에 명시된 타입과 일치해야 합니다. 이름이 같은 선언이 서로를 가리는 경우에도 이름만으로 정의를 식별하지 않습니다.

타입

타입 의미
bool 논리값 false 또는 true
i1, i8, i16, i32, i64, i128 지정된 비트 폭의 부호 있는 정수
u1, u8, u16, u32, u64, u128 지정된 비트 폭의 부호 없는 정수
f16, f32, f64 지정된 비트 폭의 부동소수점 값
ptr<T> T 타입 값을 가리키는 포인터
array<T, N> 같은 타입의 원소 N개
struct{T, ...} 순서가 있는 구조체 필드
tuple<T, ...> 순서가 있는 튜플 원소
void 결과 없음

bool, i1, u1은 서로 다른 타입입니다. signed i1은 −1과 0, unsigned u1은 0과 1을 표현합니다. 정수 1은 암묵적으로 논리 조건이 되지 않습니다. 조건 분기, Select의 조건, trap_if는 Bool 피연산자를 요구합니다.

저장 크기는 값의 비트 수만으로 정해지지 않고 타깃 레이아웃을 따릅니다. 예를 들어 i1의 값은 1비트지만 메모리에서는 최소 1바이트를 차지합니다.

함수와 호출

함수에는 전체 매개변수·결과 타입, 호출 규약, linkage를 명시합니다. 직접 호출과 간접 호출은 호출 대상의 서명과 일치해야 합니다. void 호출은 결과 ID가 없습니다. nonvoid 호출은 O0에서 결과를 사용하지 않더라도 결과 정의를 유지합니다.

반환은 함수의 결과 타입과 일치해야 합니다. void 반환은 값을 전달하지 않으며, nonvoid 반환은 선언된 결과 타입의 값을 전달합니다.

블록과 값의 사용 가능성

각 블록에는 고유한 식별자와 정확히 하나의 terminator가 있습니다. 분기 대상은 같은 함수에 속해야 합니다. 진입 블록은 반드시 존재하며 선행 간선과 phi를 가질 수 없습니다. 루프를 만들 때는 진입 블록에서 별도의 루프 헤더로 분기합니다.

실행 가능한 경로에서 값의 정의는 일반적인 사용 지점을 지배해야 합니다. 즉, 진입점에서 사용 지점으로 가는 모든 경로가 그 정의를 지나야 합니다. 같은 블록에서는 정의가 사용보다 앞에 있어야 합니다. 블록의 저장 순서는 지배 관계를 결정하지 않습니다.

진입점에서 left 또는 right로 분기한 뒤 join에서 합류한다고 가정합니다. left에서만 정의한 값은 join에서 일반 값으로 사용할 수 없습니다. right를 지나는 경로에는 정의가 없기 때문입니다. 각 선행 블록의 값을 입력으로 받는 phi로 합쳐야 합니다.

도달 불가능한 블록도 모듈에 보존됩니다. 검증기는 해당 블록의 식별자·타입·피연산자·분기 구조를 계속 검사합니다. 도달 불가능한 블록의 정의가 도달 가능한 경로의 일반 사용에 값을 공급할 수는 없습니다.

Phi 명령

phi는 블록 안의 모든 일반 명령보다 앞에 놓입니다. 서로 다른 선행 블록마다 정확히 하나의 입력이 필요합니다. 입력 값은 phi와 같은 타입이어야 하며, 해당 선행 블록의 끝에서 사용할 수 있어야 합니다.

하나의 선행 블록에서 간선이 여러 개 들어와도 입력은 하나입니다. 루프 phi는 모듈 저장 순서상 나중에 나오는 블록의 값이라도 반복 간선에서 계산되는 값이면 참조할 수 있습니다. 누락·중복·무관한 선행 블록과 잘못된 타입의 입력은 검증 오류입니다.

평가와 선택

Whale AST는 호출 대상과 하위 표현식을 명시된 왼쪽부터 평가합니다. 프런트엔드는 단락 평가를 제어 흐름 분기로 표현합니다.

Select는 이미 계산된 값 중 하나를 선택합니다. 어느 쪽 입력의 계산도 생략하지 않습니다. 예를 들어 안전한 값을 선택하더라도 다른 입력을 계산하면서 발생한 trap을 피할 수 없습니다. 특정 경로에서만 실행해야 하는 계산은 조건부 블록 안에 배치해야 합니다.

검증과 trap

잘못된 IR은 검증 단계에서 거부합니다. 실행 조건 위반은 정의된 trap으로 처리하며, undefpoison은 허용되는 값이 아닙니다. builder 오용, 중복 정의, 두 번째 terminator 추가는 구조적 오류로 반환해야 합니다.

trap은 이유·소스 위치·IR ID를 포함하며 이후 실행을 중단합니다. native 실행에서는 프로그램을 종료하고 인터프리터 API에서는 Trap 오류를 반환합니다. 이전 부작용은 보존하지만 버퍼 flush·소멸자 호출·스택 unwinding은 보장하지 않습니다.

이 보장은 검증된 IR과 추적 메모리에 적용됩니다. 외부 C·원시 주소·인라인 어셈블리는 별도 계약을 가지며, 그 경계 밖의 위반까지 항상 검출하지는 않습니다. 메모리 모델을 참고하세요.

교환 형식과 텍스트 표현

AST와 typed IR은 각각의 format version과 공통 semantics version을 사용합니다. 읽는 쪽은 무버전·알 수 없는 버전·필드·기능·중복 JSON 키를 거부해야 합니다. 생성자는 지원하지 않는 속성이 조용히 무시될 것이라고 가정해서는 안 됩니다.

정수는 비트 폭·signedness·문자열 숫자로 전달합니다. 부동소수점 상수는 폭과 정확한 비트열로 전달합니다. 텍스트 IR의 round-trip은 이름·ID·타입·상수·순서·속성·메타데이터를 보존해야 합니다. 공백과 주석 배치는 보존 대상이 아닙니다.

이 절은 교환 형식의 요구 사항이며 JSON 스키마나 완전한 텍스트 문법은 아닙니다. 파서와 직렬화기를 선택하기 전에 지원 현황을 확인하세요.