3

그래서 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: = 두 번째 컴파일 과정에서 실제 주소로 해석 될 내용입니다.

내 질문에 다음 스위치 문을 컴파일하는 다른 방법은 무엇입니까? 내 방식은 연속 된 범위의 사례 값에 대한 색인 된 점프 테이블보다 훨씬 작지만 큰 간격이있는 경우 잘 수행됩니다.

+0

비슷하고 색인 된 점프 : 목록과 루프에 값을 넣고 색인 점프를 수행하십시오. 그러면 큰 차이가있는 값을 처리 할 수 ​​있습니다. – cup

+2

분기의 2 진 트리를 사용하여 평균 분기 수를 최소화하십시오. 연속적이거나 연속적 인 모든 시퀀스는 점프 테이블을 사용하여 수행해야합니다. –

+0

값 사이의 갭이 너무 큰 경우가 아니라면 일반적으로 점프 테이블을 사용해야합니다. 그러나 소스 값 집합을 좀 더 간결하게 매핑하거나 시퀀스 나 ifs 트리로 변환하는 저렴한 함수를 찾아야합니다 . –

답변

3

먼저 모든 사례를 정렬하십시오. 그 다음에는 연속적이거나 연속적으로 가까운 모든 시퀀스를 식별하여 점프 테이블로 처리되는 단일 단위로 처리하십시오. 그런 다음 비교 및 ​​점프의 선형 순서 대신 평균 점프 수를 최소화하기 위해 분기의 균형 이진 트리를 사용하십시오. 사례의 중앙값 또는 사례 블록을 재귀 적으로 비교하여이를 수행합니다.