2011-12-08 3 views
2

Renjin (R for the JVM) 용 바이트 코드 컴파일러에서 작업 중이며 중간 3 주소 코드 (TAC) 표현을 바이트 코드로 변환하는 것을 실험하고 있습니다. 필자가 컨설팅 한 컴파일러의 모든 교과서는 코드 생성 중에 레지스터 할당을 논의하지만 JVM과 같은 스택 기반 가상 시스템에서 코드 생성을위한 리소스를 찾을 수 없었습니다.3 개의 주소 코드에서 JVM 바이트 코드로 코드 생성

간단한 TAC 명령어는 바이트 코드로 변환하는 것이 쉽지만 임시 변수가 포함될 때 약간 손실됩니다. 어떤 사람이 이것을 설명하는 자원에 대한 조언을 갖고 있습니까?

x + sqrt(x * y) 

TAC IR :

원래 R 코드는 다음과 같습니다 : 여기

이 완벽한 예입니다

0: _t2 := primitive<*>(x, y) 
1: _t3 := primitive<sqrt>(_t2) 
2: return primitive<+>(x, _t3) 

(잠시 사실을 무시 taht를 우리는 할 수 없습니다 컴파일시 항상 함수 호출을 프리미티브로 변환)

결과 JVM 바이트 코드 이 같은 LD 모양 (대략) 일 :

aload_x 
dup 
aload_y 
invokestatic r/primitives/Ops.multiply(Lr/lang/Vector;Lr/lang/Vector;) 
invokestatic r/primitives/Ops.sqrt(Lr/lang/Vector;) 
invokestatic r/primitives/Ops.plus(Lr/lang/Vector;Lr/lang/Vector;) 
areturn 

기본적으로, 프로그램의 상단에, 나는 이미 내가 시간에 의해 스택의 시작 부분에 지역 변수 X를 필요 해요 생각해야 나는 TAC 지침 2에 도달했다. 나는 이것을 수동으로 생각할 수있다. 그러나 나는 올바르게 이것을 할 알고리즘을 생각하는 데 어려움을 겪고있다. 어떤 포인터?

답변

2

3- 주소 표현을 스택으로 변환하는 것이 3- 주소로 변환하는 것보다 쉽습니다.

  1. 양식 기본 블록
  2. 을는 기본 블록 내에서
  3. 빌드 식 트리를 SSA-변환 수행
  4. 레지스터 schedulling (및 phi- 제거를 수행

    당신의 순서는 다음과 같아야 동시에) 이전 단계에서 제거하지 않은 레지스터에 대해 로컬 변수를 할당합니다.

  5. JVM 코드를 내 보냅니다 - 레지스터가 변수에 들어가면 표현식 트리가 아주 단순합니다. 스택 작업에 ​​xpanded
+0

와우! 고마워, 내가 찾던 바로 그거야. 질문 : 각 기본 블록 내에서 또는 전체 절차에서 SSA 변환을 수행해야합니까? 자습서, 교과서 또는 기타 리소스에 대한 지침이 있습니까? – akbertram

+0

SSA 변환은 절차 전반에 걸쳐 수행됩니다. http://en.wikipedia.org/wiki/Single_static_assignment 변수를 할당하는 기본 블록 (여러 개의 할당 위치가있는)에 대한 우위 경계를 찾아야합니다. 그곳에 phi 노드를 삽입하고 여분의 phis를 제거하십시오 (nb : 일부는 순환 종속성을 가질 수 있습니다). –

+0

@akbertram,'LLVM'은 여기서 유용한 영감의 원천이 될 수 있습니다. 그 후에 중간 표현을 안전하게 모델링 할 수 있습니다. 중요한 설계 결정은 하나의 레지스터를 다른 레지스터에 할당하는 것을 허용하지 않고 레지스터에 상수를 할당 할 수 없도록하고 항상 레지스터 대신 대신 사용합니다. –

관련 문제