그래서 C의 하위 집합을 학습용으로 간단한 스택 VM으로 컴파일 중이며 switch 문을 가장 잘 컴파일하는 방법을 알고 싶습니다.간단한 VM에 대한 switch 문 컴파일
는switch (e) {
case 0: { ... }
case 1: { ... }
...
case k: { ... }
}
내가 겪고있어이 책은 인덱스 점프하지만,이 책에서 설명하는 간단한 방식은 경우에만 값의 연속, 상승 범위 작동으로 컴파일 할 수있는 간단한 방법을 제공합니다.
지금은 첫 번째 패스에 기호 라벨을 사용하고 있고 두 번째 패스 중에 레이블을 사용하면 레이블을 사용하여 지시 사항을 상당히 쌓을 수있는 초기 컴파일을 단순화하기 때문에 실제 점프 대상으로 레이블을 해결할 것입니다. 제 아이디어는 책에있는 내용을 다음 순서로 어떤 순서로든 대소 문자 순서로 일반화하는 것입니다. 케이스가 c1, c2, ..., cn
값과 해당 레이블 j1, j2, ..., jn
다음 e
의 값을 가정 명령의 다음 시퀀스를 생성 호출하면 스택의 상단에 :
dup, loadc c1, eq, jumpnz j1,
dup, loadc c2, eq, jumpnz j2,
...
dup, loadc cn, eq, jumpnz jn,
pop, jump :default
j1: ...
j2: ...
...
jn: ...
default: ...
표기법 희망 분명 그렇지 않은 경우 : dup
= 중복 값에 loadc c
= 스택 맨 위에 상수 값 c
넣기 eq
= 스택의 상위 2 개 값 비교 및 비교를 기준으로 0 또는 1 밀어 넣기 jumpnz j
= 최상위 스택 값이 0이 아닌 경우 j
레이블로 점프 , label:
= 두 번째 컴파일 과정에서 실제 주소로 해석 될 내용입니다.
내 질문에 다음 스위치 문을 컴파일하는 다른 방법은 무엇입니까? 내 방식은 연속 된 범위의 사례 값에 대한 색인 된 점프 테이블보다 훨씬 작지만 큰 간격이있는 경우 잘 수행됩니다.
비슷하고 색인 된 점프 : 목록과 루프에 값을 넣고 색인 점프를 수행하십시오. 그러면 큰 차이가있는 값을 처리 할 수 있습니다. – cup
분기의 2 진 트리를 사용하여 평균 분기 수를 최소화하십시오. 연속적이거나 연속적 인 모든 시퀀스는 점프 테이블을 사용하여 수행해야합니다. –
값 사이의 갭이 너무 큰 경우가 아니라면 일반적으로 점프 테이블을 사용해야합니다. 그러나 소스 값 집합을 좀 더 간결하게 매핑하거나 시퀀스 나 ifs 트리로 변환하는 저렴한 함수를 찾아야합니다 . –