KR960003138B1 - 다중 언어 최적화 컴파일러의 유도 수식 분석 - Google Patents

다중 언어 최적화 컴파일러의 유도 수식 분석 Download PDF

Info

Publication number
KR960003138B1
KR960003138B1 KR1019920702693A KR920702693A KR960003138B1 KR 960003138 B1 KR960003138 B1 KR 960003138B1 KR 1019920702693 A KR1019920702693 A KR 1019920702693A KR 920702693 A KR920702693 A KR 920702693A KR 960003138 B1 KR960003138 B1 KR 960003138B1
Authority
KR
South Korea
Prior art keywords
gem
type
tuple
tuples
code
Prior art date
Application number
KR1019920702693A
Other languages
English (en)
Inventor
데이비드 스콧트 블리크스테인
캐롤라인 스위니 데이비드슨
로버트 네일 쥬니어 페이만
리차드 배리 그로브
스티븐 오. 호브스
데니스 죠셉 머피
Original Assignee
디지탈 이큅먼트 코오포레이숀
로날드 이. 마이릭
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by 디지탈 이큅먼트 코오포레이숀, 로날드 이. 마이릭 filed Critical 디지탈 이큅먼트 코오포레이숀
Application granted granted Critical
Publication of KR960003138B1 publication Critical patent/KR960003138B1/ko

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/40Transformation of program code
    • G06F8/41Compilation
    • G06F8/43Checking; Contextual analysis
    • G06F8/433Dependency analysis; Data or control flow analysis
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/40Transformation of program code
    • G06F8/41Compilation
    • G06F8/43Checking; Contextual analysis
    • G06F8/436Semantic checking
    • G06F8/437Type checking
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/40Transformation of program code
    • G06F8/41Compilation
    • G06F8/44Encoding
    • G06F8/443Optimisation
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/40Transformation of program code
    • G06F8/41Compilation
    • G06F8/44Encoding
    • G06F8/447Target code generation

Abstract

내용 없음.

Description

[발명의 명칭]
다중 언어 최적화 컴파일러의 유도 수식 분석
[도면의 간단한 설명]
본 발명의 특징으로 생각되는 신규의 구성은 부속 청구범위에 기재된다. 그러나 발명 그 자체 뿐만 아니라 그것의 다른 특징 및 장점은 첨부 도면을 참조로 한 다음의 특정 실시예에 대한 상세한 설명에 의해 가장 잘 이해될 수 있을 것이다.
제1도는 본 발명의 특징을 사용한 컴파일러의 개략도이다.
제2도는 본 발명의 다양한 특징을 갖는 방법이 실행될 수 있는 호스트 컴퓨터의 블럭도이다.
제3도는 제1도의 컴파일러에 의해 번역되는 코드를 소스 코드 형태, 중간 언어 형태, 트리 형태(tree form) 및 어셈블리 언어 형태로 나타낸 도면이다.
제4도는 제1도의 컴파일러에 사용된 튜플의 데이타 구조를 나타낸 도면이다.
제5도는 제1도의 셀의 동작을 나타낸 논리 순서도이다.
제6도는 상수를 포함하는 코드 리스트의 예를 나타낸 도면이다.
제7도는 본 발명의 한 특징에 따른 타입 정의를 예시하기 위한 데이타 필드 및 관계(포인트)를 나타낸 도면이다.
[발명의 상세한 설명]
[발명의 배경]
본 발명은 디지탈 컴퓨터 프로그램용 컴파일러에 관한 것으로서, 구체적으로는 다수의 상이한 타겟 머신(target machine)용 코드를 발생하기 위하여 다수의 상이한 컴퓨터 언어와 사용되기에 적합한 컴파일러 프레임워크(framework)에 관한 것이다.
컴파일러는 보통 특정 오퍼레이팅 시스템을 갖는 특정 타겟 머신의 실행을 위해 특정 소스 언어를 목적 코드로 변화하도록 구성된다. 예를 들어, 포트란 컴파일러(Fortran Compiler)는 VMS 오퍼레이팅 시스템을 사용하는 VAX 아키텍쳐를 갖는 컴퓨터용 코드를 발생시키는데 이용될 수 있고, 또는 C 컴파일러 MS/DOS를 실행하는 80386 컴퓨터용 코드를 발생시키는데 이용될 수 있다. 이러한 언어 및 타겟 특정 컴파일러들의 중간부들은 공통의 구조 및 기능을 상당량 공유하지만, 새로운 컴파일러의 구성은 기존의 컴파일러의 구성 부분의 일부를 사용하고 다른 부분을 변경함으로써 얻어질 수 있다. 그럼에도 불구하고, 소스 언어와 타겟 머신의 각각의 조합에 대해 새로운 컴파일러를 구성하는 것이 관행화되어 왔고, 또 새로운 고성능 컴퓨터 아키텍쳐가 고안될 경우 공통으로 사용된 소스 언어 각각에 대하여 컴파일러를 재기입하는 작업이 주작업이 되어 왔다.
컴퓨터를 이용한 소프트웨어 엔지니어링(CASE) 분야는 컴파일러 기술에 크게 좌우된다. CASE 도구 및 프로그래밍 환경은 코어 컴파일러(core compiler)상에 구성된다. 아울러, 컴퓨터 하드웨어의 성능 사양은 보통 컴파일러 기술과 종합적으로 관련된다. 프로세서의 속도는 통상 고급 언어 밴치마크(benchmark)로 측정되므로, 컴파일러의 최적화는 새로운 컴퓨터 장비의 가격-성능 요소에 영향을 줄 수 있다.
각종 상이한 고급 언어 및 상이한 타켓 컴퓨터 아키텍쳐용 컴파일러의 구성을 용이하게 하기 위해서는, 컴퓨터 프레임워크의 핵심 부품의 공통성을 높이는 것이 바람직하다. 컴파일러의 전단은 소스 코드 모듈을 직접 액세스하므로 언어 특정성이 필요하며, 파스칼(Pascal)을 해석하도록 구성된 컴파일러 전단은 C를 해석하는 데에는 이용되지 않을 것이다.
이와 마찬가지로, 컴파일러 후단의 코드 발생기는 타겟 컴퓨터 아키텍쳐의 명령 세트를 사용하여야 하므로 머신 특정성을 갖는다. 따라서, 보다 일반적으로 만들어질 수가 있는 것은 컴파일러의 중간부 구성요소이다. 컴파일러 전단은 보통 소스 코드를 중간 언어로 번역하는 기능을 하므로, 원래 고급 소스 언어로 쓰여졌던 프로그램은 컴파일러의 내부 동작을 위해 보다 기초적인 언어로 나타나게 된다. 그 전단부는 보통 심볼 테이블(symbol table)과 함께 소위 그래프의 형태로 중간 언어의 프로그램 또는 루우틴을 표시한다. 이들 두가지 데이타 구조, 즉 중간 언어 그래프 및 심볼 테이블은 컴파일러에 의해 내부적으로 사용되는 프로그램의 표시이다. 따라서, 중간 언어를 만들고 범용 또는 일반 문자의 심볼 테이블을 구성함으로써, 전단 다음의 구성요소들은 보다 일반적인 것이 될 수 있다.
컴파일러 전단이 중간 언어 그래프 및 심볼 테이블을 발생한 후, 보통 여러가지 최적화 기술이 실시된다. 타겟 머신의 실행 속도를 최적화하기 위해 순서 그래프가 재배열 즉 프로그램이 다시 쓰여진다. 어떤 최적화는 타겟 특정성을 갖지만 대부분은 일반성을 갖는다. 통상 사용되는 최적화는 코드 모션(code motion), 강도저하(strength reduction) 등이다. 다음 컴파일러의 내부 조직은 메모리 및 레지스터 할당이다. 이 시점까지, 데이타 참조(data reference)는 어디에 기억되는가에 관계없이 변수 또는 상수로 명명되지만, 이제 데이타 참조는 특정 레지스터 및 메모리 변위 장소(아직 메모리 어드레스가 아님)와 같은 보다 구체적인 위치에 할당된다. 이 시점에서, 레지스터내의 데이타를 메모리 참조가 최소화되게 유지시키는 레지스터의 할당의 형태로, 더욱 최적화가 가능해지며, 따라서 프로그램이 레지스터 사용을 최적화하도록 다시 재배열 될 수 있다. 레지스터 할당은 또한 타겟 머신과 어느 정도 관계를 갖기 때문에, 컴파일러의 일반적 성질은 타겟 CPU의 레지스터 세트에 대한 번호, 크기 및 특수 지정을 특정하는 것을 수용하여야만 한다. 레지스터 및 메모리 할당에 이어서, 컴파일러는 목적 코드 이미지를 생성하는 코드 발생 단계를 실시하는데, 이것은 물론 타겟 머신 언어 또는 명령 세트 즉 머신 특정성을 갖는다. 그다음, 목적 코드 이미지는 모드 머신 특정성을 갖는 다양한 런 타임 모듈(run-time module)을 추가하여 실행가능한 패키지를 생성하도록 링크된다.
전형적인 컴파일러 구성에서는, 중간 언어 그래프의 구조, 최적화, 레지스터 및 메모리 할당 단계가 보다 일반화되기 쉽다는 것을 알 수 있다. 그러나, 오늘날 가장 흔히 사용되는 고급 언어의 실질적인 차이 및 타겟 머신 아키텍쳐의 차이로 인해, 일반적인 컴파일러 코어의 구성을 방해하는 장애 요인들이 존재한다.
[발명의 개요]
본 발명의 한 실시예에 의하면, 일반적 “셀”(shell) 또는 제어 및 시퀀싱 메카니즘 및 일반적 후단을 사용하는 컴파일러 프레임워크가 제공된다(물론 코드 발생기는 타겟 특정성을 갖는다). 그 일반적 후단은 최적화, 레지스터와 메모리 할당 및 코드 발생 기능을 제공한다. 그 셀은 각종 호스트 컴퓨터에 대하여 실행될 수 있고, 후단의 코드 발생 기능은 다수의 컴퓨터 아키텍쳐중 어떤 것에 대해서도 어떤 것에 대해서도 타겟이 맞춰질 수 있다. 전단은 코볼(Cobol), 포트란(Fortran), 파스칼(Pascal), C, C++, Ada 등과 같은 각각의 상이한 소스 언어에 대하여 설계된다. 그 전단은 소스 코드 모듈을 주사 및 분석하여 그로부터 소스 코드로 표현된 프로그램의 중간 언어 표시를 발생한다. 이 중간 언어는 통상의 방식으로 소스 코드 언어의 어떤 것도 표시할 수 있도록 구성되므로, 전단과 후단 사이의 인터페이스는 표준 형식으로 이루어지고 각각의 언어 특정성을 갖는 전단을 위해 다시 쓰여질 필요가 없다.
전단에 의해 발생된 중간 언어 표시는 튜플(tuple)을 기본 단위로 사용하고 있는데, 각 튜플은 로드(load), 스토어(store), 애드(add), 라벨(label), 브랜치(branch) 등과 같이 수행될 단일 동작을 나타낸다. 데이타 구조는 각 튜플에 대한 전단에 의해 꾸며지고 각종 필요 정보에 대한 필드를 갖는다. 전단은 주문된 튜플 시리즈와 함께 통상의 실용화된 방식과 같이 변수, 루우틴, 라벨 등의 모든 참조에 대한 심볼 테이블을 생성한다. 그 튜플은, 블럭이 루우틴 또는 라벨로 시작하여 브랜치로 끝나는 코드의 일부분인 경우 예컨대 블럭의 시작과 종료 사이에 입구와 출구가 허용되지 않는 경우, 블럭들내에 주문된 순서로 존재한다. 각 블럭은 또한 데이타 구조 또는 노드이며, 그것의 석세서(successor) 및 프리디세서(predecessor)에 대한 포인터를 포함한다(이들은 심볼 테이블내의 심볼들에 속한다). 상호 연결된 블럭들은 소위 중간 언어 그래프라 불리우는 플로우 그래프를 구성하는데, 그 플로우 그래프는 최적화, 레지스터 및 메모리 할당 등을 행하도록 후단에 의해 사용된 프로그램의 표시이다.
본 발명의 특징중 하나는 전단과 후단 사이의 인터페이스의 효과 및 종속성을 나타내기 위한 메카니즘에 있다. 튜플은 메모리에 쓰여지는 경우 효과를 가지며, 어떤 다른 노드가 쓰여질 수 있는 위치로부터 읽혀지는 경우 종속성을 갖는다. 다양한 고급 언어는 동작을 표현하는 다른 방법들을 가지면, 동일 시퀀스는 어떤 언어에서는 효과 또는 종속성을 허용할 수 있는 반면 다른 언어에서는 허용할 수 없다. 따라서, 소스 언어와 독립적인 메카니즘이 프로그램 실행 효과를 기입하기 위해 제공된다. 이 메카니즘은 컴파일러 전단이 컴파일러 후단내의 다중 언어 옵티마이저(multi-language optimizer)에 대해 상세한 언어 특정성 정보를 발생시키는 수단을 제공한다. 이 메카니즘은 공통 부표현 인식 및 코드 모션을 포함하여 적법하고 효과한 최적화를 결정하도록 전역옵티마이저(global optimizer)에 의해 사용된다. 튜플들의 중간 언어 및 구조는 정보를 포함하므로 후단(옵티마이저들)은 전단의 질문을 요구할 수 있고(중간 언어 그래프로부터 정보를 얻음), 그것으로부터 후단은 한 튜플에 대한 타겟 머신을 위해 생성된 코드의 실행이 다른 튜플에 대한 코드에 의해 계산된 값에 영향을 줄 때를 결정할 수 있다. 후단과 전단 사이의 인터페이스는 이러한 점에서 언어 독립성을 갖는다. 후단은 어떤 언어가 번역되고 있는지 알 필요가 없다. 상이한 후단(및 셀)이 각 소스 언어에 대하여 쓰여질 필요가 없지만 그 대신 최적화 컴파일러가 단지 각각의 다른 언어에 대한 전단을 설계함으로써 각 소스 언어에 대하여 제작될 수 있는 것이 잇점이다.
본 발명의 한 실시예의 다른 특징은 유도 변수를 분석하기 위한 방법을 컴파일러의 최적화부에서 사용한다는 점이다. 변수는 그것이 루우프(loop)를 통해 매 타임마다 한번 증분 또는 감분되는 경우 유도 변수라 일컬어지며, 루우프를 통해 각 타임마다 최대로 한번 실행된다. 이 최적화부는 유도 변수를 찾는 것 외에 유도 변수의 선형 함수로서 계산될 수 있는 수식인 유도성 수식을 찾는다. 이 최적화의 목적은 일반적으로 승산을 가산으로 바꾸는 것인데, 그것은 대부분의 아키텍쳐에 있어서 저렴하고 실행 속도가 신속하기 때문에 강도 저하로 알려져 있다. 유도 변수의 검출은 잠재적 유도 변수 “세트”(sets)의 사용을 필요로 하며, 각 루우프에 대하여 이것을 동적으로 행하는 것은 고가이고 복잡한 동작이므로, 여기서의 개선점은 IDEF 세트를 구성하는데 사용된 측면 효과 세트를 사용하는데 있다.
본 발명의 한 실시예의 다른 특징은 최적화부의 하나로서 포함된 “폴딩 정수”(folding constants)(K 폴딩 또는 KFOLD 루우틴으로 일컬어짐)에 대한 메카니즘이다. 이 메카니즘은 표현이 상수로 감소되어 런 타임시의 많은 시간이 소요되는 계산이 아니라 번역 시간에서 계산될 수 있는 경우를 발견하기 위한 것이다. 중요한 특징은 KFOLD가 사용자에 의해 코드화되거나 계산되기 보다는 컴파일러 프레임워크 자체에 의해 구성된다는 것이다. KFOLD 구성자는 다른 언어 특정성 전단처럼 전단으로서 기능을 하지만, 소스 코드 입력이 필요없으며, 그대신 입력이 중간 언어로 되고 단지 모든 연산자 및 모든 데이타 형태의 리스트로 구성된다. 휠씬 더 많은 완전한 KFOLD 패키지가 휠씬 저가격으로 발생될 수 있다는 것이 잇점이다.
본 발명의 한 실시예의 다른 특징은 TD 모듈이라 불리는 타입(type) 정의 메카니즘이다. 이 모듈은 링커(linker) 또는 디버거(debugger)에 의해 사용될 수 있도록 목적 모듈에서 종합될 프로그램 타입 정보를 구성함에 있어 전단 및 후단의 컴파일러에 의해 사용되는 메카니즘들을 제공한다. “타임 정보”의 발생은 심볼 테이블의 발생과 관련하여 생기며, 전단으로 하여금 프로그램 타입 정보의 추상적 표현을 후단에 대해 특정할 수 있도록 한다. TD 모듈은 전단으로 하여금 기본 타입과 추상적 타입을 기재할 수 있게 하는 서비스 루우틴을 제공한다.
아울러, 한 실시예의 특징은 멀티패스(multipass) 방식으로 코드 템플리트(templates)를 사용하여 코드발생을 행하는 방법이다. 코드 템플리트의 선택 및 적용은 번역 과정시 4개의 차등 시간에서 발생된다. 즉, (1) 패턴 선택 즉 PATSELECT 단계는 가장 좋은 코드 템플리트를 선택하도록 CONTEXT 패스에서 패턴 정합을 행한다 ; (2) CONTEXT 패스의 TNASSIGN 및 TNLIFE 작업은 표현에 대한 평가 순서를 분석하고 코드 템플리트에 비로컬한(nonlocal) 수명을 갖는 일시적 명칭(TN)을 할당하도록 선택된 템플리트의 콘텍스트 액션(context action)을 사용한다 ; (3) TNBIND 패스는 코드 템플리트에 로컬한 (local) 수명을 갖는 TN을 할당하도록 선택된 템플리트의 바인딩 액션(binding action)을 사용한다 ; (4) 최종적으로, CODE 패스는 목적 코드의 발생을 안내하도록 선택된 템플리트의 코드 발생 액션을 사용한다.
[특정 실시예에 대한 상세한 설명]
제1도를 참조하면, 본 발명의 한 실시예에 따른 컴파일러 프레임워크(10)은 휴대가능하고 목표 재설정가능한 컴파일러의 생성을 위한 언어 독립성을 갖는 프레임워크이다. 컴파일러 프레임워크(10)는 셀(11)이라 불리우는 휴대가능한 오퍼레이팅 시스템 인터페이스와 목표 재설정가능한 옵티마이저 및 코드 발생기(12)(후단)으로 구성된다. 셀(11)은 호스트 컴퓨터를 실행하는 VAX/VMS, Unix 등과 같은 수종의 오퍼레이팅 시스템 어느 것과도 기능을 행하기에 적합하다는 점에서 휴대가능하다. 그 셀은 제2도에서 도시한 바와 같이 전형적으로 시스템 버스(16)에 의해 주 메모리(15)에 결합됨과 동시에 I/O 제어기(18)에 의해 디스크 기억장치(17)에 결합되는 CPU(14)를 포함하는 호스트 계산 시스템을 샐행하는 이 호스트 오퍼레이팅 시스템(13)에 의해 동작한다. 셀(11) 및 컴파일러(12)는 특정 소스 언어에 대한 휴대가능하고 목표 재설정가능한 컴파일러를 생성하도록 전단(20)과 결합될 수 있다. 따라서, 본 발명의 프레임워크(10)을 기본으로 사용하는 컴파일러는 세개의 기본 요소, 즉 특정 호스트 오퍼레이팅 시스템(14)를 위해 설계되었던 셀(11)-이것은 컴파일러의 호스트 환경을 결정한다-, 특정 소스 언어(예, C, C++, 파스칼, Ada, 코볼 등)를 위한 전단 (20)-이것은 컴파일러의 소스 언어를 결정한다-그리고 특정 타겟 머신을 위한 후단(12)(즉 VAX, RISC 등과 같은 특정 아키텍쳐)-이것은 컴파일러의 타겟 머신을 결정한다-로 구성된다.
셀(11), 전단(20) 및 후단(12) 사이의 인터페이스가 고정되기 때문에, 본 발명에 따라 제작된 컴파일러의 개별 부품들은 자유롭게 교체될 수 있다. 즉, 전단(20)은 다수의 호환성을 갖는 전단, 예컨대 포트란을 위한 것, 코볼을 위한 것, 파스칼을 위한 것, C를 위한 것 등으로 구성된다. 이와 마찬가지로, VAX 컴퓨터상의 VMS 하에서 동작하도록 설계된 셀(11)은 RISC 워크스테이션상의 Unix 오퍼레이팅 시스템하에서 동작하는 셀(11)로 교체될 수 있는 반면 전단(20)과 후단(12)은 동일하게 유지될 수 있다.
셀(11)은 호스트 오퍼레이팅 시스템(13)과 컴파일러의 나머지 사이에 고정된 인터페이스를 제공한다. 첫째, 셀(11)은 오퍼레이팅 시스템(13)의 기본 구성에 휴대가능한 인터페이스를 제공한다. 예를 들어, 전단(20)은 파일 시스템의 세부, 호스트 오퍼레이팅 시스템(13)에 의한 명령 파싱(command parsing) 또는 힙(heap) 저장 할당에 대해 알 필요가 없는데, 그 이유는 모든 이들 서비스가 셀 루우틴을 통해 액세스되고 그 셀이 사용중인 오퍼레이팅 시스템(13)에 대하여 설계되기 때문이다. 둘째 셀(11)은 명령 라인 파싱, 인클루드 파일 처리(include-file processing) 및 진단 파일 발생과 같은 어떤 공통의 컴파일러 구성요소의 단일 구성을 제공함으로써 노력의 중복을 없애준다. 셋째, 이들 공통의 구성요소를 사용하는 것은 프레임워크(10)를 사용하여 생성된 컴파일러간에 일치성을 보장해준다. 즉, 프레임워크(10)을 사용하여 생성된 모든 컴파일러는 동일한 포맷으로 파일 리스트를 작성하고 명령 라인 한정사(command line qualifier)를 동일하게 처리하며 유사한 모습의 에러 메시지를 발송한다. 넷째, 셀(11)에 공통 셀 유틸리티를 갖는 것은 컴파일러의 내부적 통합을 개선시켜주는데 그 이유는 전단(20) 및 후단(12)이 동일한 기능의 셀을 사용하기 때문이다.
예를 들어, 셀 로케이터(shell locator) 패키지의 사용은 소스 파일 위치가 소스 리스팅, 전단 발생 진단, 목적 리스팅 및 디버거 정보에서 일관성있게 불리울 수 있음을 의미한다.
전단(20)은 번역중인 소스 언어를 이해하는, 프레임워크(10)에 의해 생성된 컴파일러의 유일한 구성요소이다. 이 소스 언어는 컴파일러의 입력을 정의하는 소스 코드 파일 또는 파일들(모듈 또는 모듈들)(21)의 텍스트를 발생하는데 사용되는 것이다. 전단(20)은 다수의 기능을 수행한다. 첫째, 그것은 소스 파일(21)로부터 명령 라인 정보 및 텍스트 라인을 얻록 셀(11)을 호출한다. 둘째, 전단(20)은 리스팅 파일을 제어하고 진단 메세지를 기입하여 가능한한 특정 언어에 대한 다른 파일을 작성하도록 셀(11)을 호출한다. 셋째, 전단(20)은 전단(20)과 후단(12)사이의 인터페이스(22)에 대해 사용된 언어 독립성을 갖는 내부적 표시로 파일(21)내의 소스 텍스트를 변환시키기 위해 어휘, 구문 및 어의 분석을 행한다. 넷째, 전단(20)은 내부적 표시의 정보로부터 타겟 시스템 목적 코드(23)를 발생하도록 후단(12)을 호출한다. 다섯째, 전단(20)은, 후단(12)이 후단 처리 과정중에 언어 특정성을 갖는 정보를 얻기 위해 호출 통로(24)를 통해 호출하는 루우틴을 제공한다. 제1도의 컴파일러의 프레임워크에는 실행가능한 이미지를 형성하여 타겟 머신(25)을 동작시키도록 목적으로 코드 모듈 또는 이미지(23)를 연결하는 링커가 포함되지 않는다.
컴파일러의 후단(12)으로 하여금 코드를 생성케 하는 타겟 머신(25)은 어떤 특정 아키텍쳐의 컴퓨터이다. 즉, 그것은 어떤 특정 번호 및 데이타 폭을 갖는 레지스터 세트를 구비하고, 그 로직은 특정 명령 세트를 실행하며, 특정 어드레이싱 모드가 이용될 수 있다. 그 예로는 (1) VAX 아키텍쳐, (2) MIPS, Inc. 사로부터 입수가능한 32비트 RISC 칩(부품번호 R2000 또는 R3000)을 기본 구성으로 하고 Lane씨에 의해 “MIPS R2000 RISC Architecture”, Printice-Hall, 1987에 기고된 바와 같은 아키텍쳐를 갖는 RISC 타입, 및 (3) 1990. 6. 29자로 출원된 계류중인 미국 특허원 제547,589호에 기재된 바와 같은 64비트 레지스터를 갖는 개량된 RISC 아키텍쳐를 들 수 있다. 마찬가지로 각종 다른 아키텍쳐도 가능하다.
일반적으로, 전단(20)은 그것이 소스 코드(15)로부터 인터페이스(22)의 내부적 표시로 변환중일 때 목적 코드(23)를 실행하는 타겟 머신(25)의 아키텍쳐를 고려할 필요가 없는데 그 이유는 그 내부적 표시가 타겟머신(25)의 아키텍쳐와 무관하기 때문이다. 그러나, 전단(20)의 어떤 특징은 타겟 시스템에 맞춰질 필요가 있다. 예컨대, 할당 및 정렬과 같은 데이타 표시의 양태는 타겟 머신(25) 아키텍쳐에 더 잘 부합되도록 주문 설계될 수 있고, 루우틴 호출 인수 메카니즘은 타겟 시스템 호출 표준 방식에 따라 좌우될 수 있다. 그리고 런타임 라이브러리(library) 인터페이스는 아마도 각 타겟 시스템에 대해서 다르게 될 것이다.
후단(12)은 전단(20)에 의해 구성된 내부적 표시(22)를 타겟 시스템 목적 코드(23)로 번역하는 기능을 한다. 후단(12)은 최적화(26), 코드 발생(27), 메모리 및 레지스터 할당(28) 및 목적 파일 방출(29)의 기본 기능을 수행한다. 최적화 기능은 내부적 표시로 있을 때의 코드에 대하여 수행된다. 후단(12)은 또한 심볼 테이블(30) 및 중간 언어 데이타 구조를 생성하도록 전단(20)에 의해 호출되는 유틸리티 루우틴을 포함한다.
사용자(즉, 컴퓨터 시스템이 오퍼레이팅 시스템(13)를 실행중인 경우 제2도의 컴퓨터 시스템의 사용자)가 제1도의 컴파일러를 불러낼 때, 셀(11)은 제어 신호를 수신한다. 셀(11)은 전단(20)을 호출하여 소스 파일(15)로부터의 입력 스트림(input stream)을 목적 파일(23)로 번역한다. 전단(20)은 후단(12)을 호출하여 목적 파일(23)내의 각 개별 루우틴용 코드를 발생하거나, 혹은 전체 모듈용 코드를 한번에 발생할 후단 구동기를 호출할 수도 있다.
전단(20)은 소스 코드(21)를 분석하여 소스 코드로 표현된 프로그램의 중간 언어 버전을 발생한다. 중간 언어의 기본 구조는 튜플이다. 튜플은 소스 언어로 한 동작을 수행하는 표현이다. 예컨대, 제3도를 참조하면, 소스 언어로 나타낸 바와 같은 표현식
I=J+1
은 중간 언어로 표시하기 위한 4개의 튜플로 분할되는데, 이것은 $1, $2, $3, $4의 번호가 매겨진다. 이와같이 코드를 IL로 표현하는 방법은 아이템(31)으로 표시된 인출(fetch)인 제1튜플 $1을 포함하는데 그 인출의 목적은 심볼 J이다. 다음 튜플은 역시 심볼 “1”을 참조하는 아이템(32)의 리터럴(literal)이다. 그다음 튜플은 튜플 $1 및 s2의 결과를 참조하는 아이템(33)의 애드(Add)이다. 마지막 튜플은 튜플 $3의 결과를 참조하여 심볼 테이블에 심볼 I의 결과를 두는 아이템(34)의 스토어(store)이다. 그 표현은 또한 제3도에 도시한 바와 같은 논리 트리로서 표현될 수 있으며, 여기서 튜플은 동일 참조 번호로 식별된다. 이 소스 코드의 동일 라인은 레지스터 파일내의 REG4와 같은 어떤 레지스터를 사용하여 세 개의 명령 LOAD, ADD 정수 및 STORE처럼 제3도에 도시된 일반적인 형태로 RISC 타입 타겟 머신용 어셈블리로서 표현될 수 있다. 혹은, CISC 머신의 경우 방출된 코드가 단지 도면에 도시한 바와 같은 단일 명령 ADD#1, J, I일 수도 있다.
이로써, 튜플은 컴퓨터 프로그램의 기본 표현이 되며, 본 발명에서 사용된 형태에서는 적어도, (1) 연산자 및 타입 필드(36), 예컨대 인출, 스토어, 애드 등, (2) 소스 모듈(21)내에서 튜플에 해당하는 소스가 위치하는 장소를 정의하기 위한 로케이터(locator)(37), (3) 제3도에서의 I 및 #1 튜플 $1과 $2에 대한 포인터와 같은 다른 튜플, 리터럴 노드 또는 심볼 노드에 대한 피연산자 포인터(operand pointer)(38)를 포함하는, 제4도에 표시된 요소들을 내장하는 데이타 구조(35)이다. 튜플은 또한 예컨대 라벨, 조건부 브랜치, 인수(호출용) 또는 SymRef(심볼 테이블내의 심볼)를 포함할 수도 있는 속성(attribute) 필드(39)를 갖는다. 튜플은 이 튜플의 순서를 블럭으로 타나낸 번호 필드(40)를 갖는다.
전단(20)은 소스 코드를 분석하여 튜플을 식별한 다음 코드의 기본 블럭을 식별한다. 코드 블럭을 최초 및 최종 튜플 사이에 입구 또는 출구를 갖지 않는 일련의 튜플로서 정의된다. 통상적으로, 블럭은 라벨 또는 루우틴 입구에서 시작하여 다른 라벨의 브랜치에서 끝난다. 전단(20)의 작업은 소스 코드(21)를 분석하여 튜플 및 블럭을 식별하는 일인데 그것은 물론 전단이 언어 특정성을 갖는 것을 필요로 한다. 따라서, 튜플은 이 튜플이 블럭의 시작인지 블럭의 끝인지의 여부를 알려주는 필드(41)를 포함한다.
이하 상세히 논의된 바와 같이, 본 발명의 한 특징은 효과(effect)를 표시하는 방법이다. 튜플은, 만약 그것이(IL 레벨에서 심볼로서 표현된) 메모리 위치에 기억 또는 기입하거나, 혹은 또 다른 튜플이 어떤 위치에 무엇을 기입하느냐에 종속적이면, 효과를 가진다. 따라서, 제3도의 실시예에서는, 튜플 $4가 효과(I에 기억)를 가지며 튜플 $1은 종송성(J의 내용)을 갖는다. 따라서, 제4도에 표시된 튜플 데이타 구조는 이 튜플의 효과 및 종속성을 기억하도록 필드(42,43)를 갖는다.
제1도의 컴파일러의 한번의 실행은 제5도의 순서도에 예시한 바와 같이 셀(11)에 의해 구동된다. 제5도의 아이템(45)에 표시된 것처럼, 셀(11)은 제1도의 컴파일러가 오퍼레이팅 시스템(13)을 통해 사용자에 의해 호출될 때 제어 명령을 수신한다. 명령 라인내의 사용자는 동작되어질 모듈(21)의 “플러스 리스트”(plus-list) 또는 리스트를 특정한다. 다음 단계는 아이템(46)으로 표시된 전단에 대한 어떤 필요한 초기화를 행하는 전단 루우틴 GEM$XX_INIT이 셀(11)에 의해 호출되는 것이다. 이 전단 루우틴 GEM$SS_INIT는 부록에 기재된다. 다음, 셀(11)은 전역 명령 한정사(global command qualifiers)를 분석하여 아이템(47)으로 표시한 바와 같이 전단 루우틴 GEM$XX_PROCESS_GLOBALS를 호출한다. 이어서, 컴파일러를 호출하도록 오퍼레이팅 시스템(13) 레벨에서 사용된 명령 라인의 각 “플러스 리스트”(콤마-분리형 엔티티(comma-separated entity)에서 대하여, 셀은 일련의 액션을 실행하며, 이것은 플러스 리스트를 검사하도록 판별지점(48)을 사용하는 루우프에 의해 실현된다. 플러스 리스트에 남겨진 항목이 있는 한, 아이템(49-52)로 나타낸 액션이 실행된다. 이 액션들은 명령 라인에서 특정된 소스 파일(21)을 액세스하여 그들을 위한 입력 스트림을 생성하는 것(아이템(49)로 나타냄)과, 이어서 로컬 한정사(local qualifier)(그 플러스 리스트에 특정)를 분석하여 그들에 대한 전단 결정 처리를 행하도록 GEM$XX-PROCESS_LOCALS를 호출한 다음 한정사에 의해 특정된 출력 파일을 여는것(아이템(50)으로 나타냄)을 포함한다. 그 루우프내의 액션은 입력 스트림을 번역하도록 전단 루우틴 GEM$XX_COMPILE을 호출하는 것(아이템(51)로 나타냄)과, 이어서 출력 파일을 닫는 것(아이템(52)로 나타냄)을 포함한다. 루우프가 실현되지 않아 모든 플러스 리스트 항목이 처리되었음을 나타낼 경우, 다음 단계는 전단 클린업(front-end clean up)을 행하도록 전단 루우틴 GEM$XX-FINI를 호출하는 것(아이템(53)으로 표시)이다. 이어서, 실행이 종료되고 제어 명령을 호출기(invoker)로 복귀시킨다(아이템(54)로 표시).
셀(11)은 단일 입력 스트림을 번역하도록 GEM$XX_COMPILE을 호출한다. 입력 스트림은 컴파일러 명령 라인내의 단일 “플러스 리스트”에서 특정된 소스 파일 또는 모듈(21) 뿐만 아니라 어떤 내장 파일 또는 라이브러리 텍스트(library text)의 연결(concatenation)을 나타낸다. 생략성(default)에 의해, 입력 스트림의 번역시 컴파일러가 전단(20)으로 하여금 다수의 목적 파일(23)을 특정하도록 하지만, 단일 입력 스트림을 번역하는 것은 단일 목적 파일(23)을 생성한다.
GEM$XX_COMPILE을 호출하기 전에, 셀(11)은 입력 스트림을 생성하여 로컬 한정사를 분석하고, 출력 파일을 연다. GEM$XX_COMPILE을 호출한 후, 셀(11)은 모든 입력 및 출력 파일을 닫는다.
전단(20)(CEM$XX_COMPILE 및 그것으로부터 호출되는 전단 루우틴)은 입력 스트림으로부터 소스 레코드(21)를 읽어내서 인터페이스(22)의 중간 표시(중간 언어 그래프의 튜플, 블럭 등 및 심볼 테이블을 포함)로 변환하고 후단(12)을 호출하여 그 중간 표시를 목적 파일(23)내의 목적 코드로 변환한다.
목적 파일(23)은 다수의 목적 모듈을 포함할 수도 있다. 파스칼은 전체 입력 스트림용의 단일 목적 모듈(MODULE 또는 PROGRAM)를 생성한다. 포트란(한 실시예에서)은 입력 스트림내의 각 END 문에 대해 별도의 목적 모듈을 생성한다. BLISS는 각 MODULE용의 목적 모듈을 생성한다.
목적 모듈(23)을 생성하기 위해, 전단(20)은 입력 스트림 또는 그것의 어떤 시퀸스(소스 모듈(21)이라고도 할 수 있음)을 인터페이스(22)에 대한 내부적 표시로 변환하는데, 그 내부적 표시는 모듈에 대한 심볼 테이블(30) 및 각 루우틴에 대한 중간 언어 그래프(55)로 구성된다. 이어서 전단(20)은 후단 루우틴을 다시 호출하여 목적 모듈(23)을 초기화하고, 기억 할당(28)을 통해 심볼 테이블(30)내의 심볼에 대한 기억부를 할당하고, 그 기억부를 초기화하고, 에미터(29)를 통해 루우틴용 코드를 발생하고 목적 모듈(23)을 완성한다.
컴파일러는 패키지의 집합으로 구성되는데, 각 패키지는 번역 과정의 어떤 단계와 관계되는 루틴 또는 데이타 구조의 집합을 정의한다. 각 패키지는 일반적으로 패키지 기능의 약어인 2문자 코드로 식별된다. 패키지에 대한 인터페이스는 명세 파일에 의해 정의된다. 패키지가 ZZ로 명명되면, 그것의 명세 파일은 GEM$ZZ. SDL이 될 것이다.
패키지 명세 파일에서 선언된 어떤 심볼은 그 패키지로부터 방출되는 것으로 일컬어진다. 일반적으로, 패키지 ZZ로부터 방출된 심볼은 GEM$ZZ_로서 시작되는 명칭을 가진다. 전역 및 방출 명칭에 대한 특정 접두어 표현 규약은 표 1에 기재되어 있다.
셀(11)은 통상의 컴파일러 동작을 보조하는 루우틴의 집합이다. 셀의 구성 요소는 상호 연관 관계를 가지므로, 어떤 셀 구성 요소를 사용하는 프로그램은 전체 셀을 얻는다. 그러나, 프로그램이 후단(12)을 사용치 않고 셀(11)을 사용하는 것도 가능하다. 이것은 생산-한정 특성(producton-quality features)(입력 파일 연결 및 포함, 명령 라인 분석, 진단 파일 발생, 양호한 리스팅 파일 등)을 갖는 소규모 유틸리티 프로그램을 작성하는 편리한 방법이다. 셀(11)은 실제로 사용하는 어떤 프로그램의 “주 프로그램”이며, 응용 프로그램의 주요부는 후술될 규약을 사용하여 셀(11)로부터 호출되어야 한다. BLISS 프로그램으로부터 셀 패키지 ZZ를 사용하기 위해서는, 사용자가 LIBRARY'GEM$ZZ를 행한다. 다른 언어로부터 셀을 사용하기 위해서는, 사용자가 먼저 셀 명세 파일을 구현 언어(implementation language)로 변환하여야 한다.
셀 패키지는 다음의 구문으로 요약된다. 즉, 그들은 부록내의 명세 파일(GEM$ZZ.SDL 파일)에서 제공된다. 대부분의 셀 루우틴 인수(예, 정수, 문자 열 등)는 표 2에 기재된 카테고리중 하나에 속한다.
셀(11)로부터 전단(20)까지의 인터페이스는 어떤 필요 조건을 갖는다. 셀(11)은 제1도의 컴파일러가 호출될 때 제어 명령을 수신하기 때문에, 전단(20)은 셀(11)이 그것을 호출할 수 있도록 입구 지점을 선언하여야만 하며, 셀(11)에 전단 특정 정보를 통과시키도록 전역 변수를 선언하여야 한다. 전단(20)은 한 실시예에서 표 3에 기재된 전역 루우틴을 제공한다. 이 루우틴은 파라미터를 갖지 않고 또 결과없이 복귀한다.
가상 메모리 패키지(GEN $VM) : 가상 메모리 패키지는 가상 메모리를 할당하기 위한 표준 인터페이스를 제공한다. 그것은 VMS LIB $VN의 존 메모리 개념을 지원하며, 사실상 VMS하에서 GEM$VM은 LIB $VM 위의 거의 투명성의 층(transparent layer)이다. 그러나, GEM$VM 인터페이스는 어떠한 호스트 컴퓨터상에서도 변화되지 않은채 지원되도록 보장받는다.
로케이터 패키지(GEM$LO) : 로케이터는 소스 텍스트(21)의 범위(파일, 라인 및 열 번호의 시작 및 끝)를 기재한다. 텍스트 입력 패키지는 그것이 읽어낸 소스 라인쪽으로 로케이터를 복귀시킨다. 로케이터는 또한 메세지 및 디버거 테이블 발생을 용이하게 하도록 심볼 테이블(30) 및 중간 언어 노드(43)에서 사용되고 또 리스팅 파일내의 어디에서 리스팅 패키지가 액션을 수행하는가를 특정하기 위해 사용된다. 로케이터는 긴 워드(word)로서 표시된다. 로케이터 패키지는 로케이터 데이타 베이스를 유지하고, 로케이터를 생성 및 인터럽트시키는 루우틴을 제공한다. 사용자 생성 로케이터를 위한 설비가 존재하는데, 그것은 전단으로 하여금 비 표준 소스로부터 들어오는 프로그램 요소(예컨대, BLISS 매크로 또는 Ada 일반개시)를 기재하도록 독자적인 로케이터를 생성할 수 있게 한다.
텍스트 입력 패키지(GEM$TI) : 텍스트 입력 패키지는 연결 소스 파일(21), 내장 소스 파일(21), 생략성 및 관련 파일 명세를 지원하는 반면, 배후의 오퍼레이팅 시스템(13)의 I/O 아키텍쳐로부터 전단(20)을 격리시킨다. 소스 파일(21)의 텍스트는 한번에 한라인씩 판독된다. 텍스트 입력 패키지 GEM$TI는 그것이 읽어내는 각 소스 라인을 기재하는 로케이터를 생성하도록 로케이터 패키지 GEM$LO와 협동한다.
텍스트 출력 패키지(GEM$TX) : 텍스트 출력 패키지는 일정한 수의 출력 파일(44)로의 출력을 동시에 지원한다. 텍스트 입력 패키지처럼, 그것은 오퍼레이팅 시스템(13)으로부터 그것의 호출자를 격리시킨다. 이 패키지는 참조 또는 서술자(descriptor)에 의해 통과된 문자열을 기입할 것이다. 이 패키지는 자동 라인 랩핑(wrapping) 및 인덴테이션(indentation : 들여쓰기), 페이지 랩핑, 사용자 제공 페이지의 시작(user-provided start-of-page) 루우틴으로의 역호출을 제공한다.
리스팅 패키지(GEM$LS) : 리스팅 패키지는 소스 파일(21)의 사본을 포함하는 표준 포맷 리스팅 파일(텍스트 입력 패키지 GEM$TI에 의해 읽혀짐)을 로케이터로 특정된 위치에서 전단(11)에 의해 제공된 주석(annotation)과 함께 기입할 것이다. 리스팅 파일은 GEM$TX 출력 파일(44)로서 생성되며, 전단(20)은 GEM$TX 출력 루우틴을 사용하여 직접 그것에 기입할 수도 있다.
[내부적 표시]
모듈(21)의 내부적 표시는 소스 모듈(21)내의 각 루우틴에 대하여 모듈용 심볼 테이블(30) 및 컴팩트한 중간 언어 그래프(55) 또는 CILG를 포함한다. 이들은 모두 노드로 구성된 포인터 연결형 데이타 구조이다.
제1도의 프레임워크의 노드들을 정의하겠다. 전단(20)과 후단(12) 사이의 인터페이스에 사용된 모든 데이타 구조(및 후단(12)에 의해 전용으로 사용되는 대부분의 데이타 구조)는 노드들이다. 여기서 사용된 노드란 용어는 일반적으로 GEM$VM_GET와 함께 힙(heap)으로부터 할당된 기억 장치의 자체 식별용 블럭이다. 모든 노드들은 필드 GEM$NOD_KIND 및 GEM$NOD_SUBKIND를 갖는 집합형 GEM$NODE를 가진다. 카인드(kind)는 노드의 일반적 종류를 식별하는 열거형 GEM$NODE_KINDS로부터의 값이다. 서브 카인드(Subkind)는 카인드에 의해 특정된 일반적 유형의 노드들중에서 특정 카인드의 노드를 식별하는 열거형 GEN $NODE_SUBKIND로부터의 값이다. 어떤 특정 노드는 또한 그것의 카인드 필드에 의해 결정된 집합형을 갖는다. 예를 들어, 카인드가 GEM$NODE_K_SYMBOL이라면, 노드는 GEM$SYMBOL_NODE를 갖는다. 노드들과 관련된 타입은 상술한 명칭 규약을 위반하지 않는다. 인터페이스 노드 타입 및 그 관련 열거형 상수는 표4에 기재된다.
제1도의 컴파일러 프레임워크는 간단한 트리 구조의 심볼 테이블(30)을 지원하며, 여기서 심볼 노드들은 트리에서 배열된 블럭 노드들의 체인에 함께 링크된다. 컴파일러에 의해 사용된 모든 심볼 정보는 이 심볼 테이블(30)에 포함되어야 한다. 또한 번역된 프로그램의 리터럴 값을 표시하는 리터럴 노드, 변수가 할당되어질 기억 영역(PSECT 및 스택 프레임)을 나타내는 프레임 노드, 루우틴 입력 지점의 파라미터 리스트내의 요소를 나타내는 파라미터 노드가 존재한다. 심볼 테이블 구조 및 심볼 테이블 노드의 내용은 이하에서 설명될 것이다.
중간 언어는 소스 코드(21)의 모든 내부적 표시를 위해 사용되는 언어이다. 전단(20)은 컴팩트한 중간 언어 그래프(55) 또는 CILG로서 번역된 루우틴의 코드를 기재한다. 이것은 단지 제4도의 CIL 튜플 노드(35)(또한 튜플 노드 또는 튜플로서 일컬어짐)의 연결 리스트인바, 그 리스트는 각각 어떤 동작을 나타내며 그것의 피연산자를 표시하는 튜플 노드에 대한 포인터(38)를 갖는다. 튜플 노드는 심볼 테이블 노드에 대한 포인터(38)를 포함할 수도 있다. 중간 언어는 이하에서 보다 상세히 설명된다.
전단(20)은 한번에 한 노드씩 모듈(21)의 내부적 표시(22)를 생성하여 노드들을 심볼 테이블(30) 및 IL 데이타 구조(55)내로 함께 연결해야 한다. 표 5의 루우틴 및 매크로(부록에 기재됨)는 내부적 표시(22)의 데이타 구조를 생성 및 조정하기 위해 사용된다.
후단(22)은 전단(20)이 어떻게 블럭명 및 심볼명을 표시하는지에 대한 가정을 하지 않는다. 그대신, 전단(20)은 후단(12)이 이들의 명칭을 얻는데 사용할 수 있도록 표준 역할 인터페이스를 제공하는 것이 필요하다.
모든 심볼 노드는 플래그 GEM$SYM_HAS_NAME을 가지며 모든 블럭 노드는 플래그 GEM$BLK_HAS_NAME을 갖는다. 전단(20)이 심볼 또는 블럭 노드를 초기화 할 때, 전단(20)은 명칭 문자열이 이용 가능한지의 여부를 나타내도록 명칭 플래그를 세트하여야 한다(전역 및 외부 심볼, 톱레벨 모듈과 같은 어떤 심볼 및 블럭은 명칭을 가져야 한다).
ST 패키지에는 전역 변수 GEM$ST_G_GET_NAME가 존재한다. 후단을 호출하기 전에, 전단은 이 변수를 표 5에 기재된 설명에 부합되는 역호출 루우틴의 어드레스에 세트하여야 한다.
GEM$CO_COMPILE_MODULE 인터페이스를 사용하여 소스 모듈을 번역하기 위해서, 전단(즉 루우틴 GEM$XX_COMPILE)은 다음에서 설명된 각 동작을 행한다.
1. 내부적 표시 생성
전단(20)의 제1작업은 소스 모듈의 내부적 표시(22)를 생성하는 것이다. 먼저, 심볼 테이블(30) 및 관련 가상 메모리 존을 초기 설정하도록 GEM$ST_INIT를 호출하여야 한다. 이어서, GEM$T1 패키지를 사용하여 입력 스트림으로부터 소드 모듈(21)을 읽어내고 ; 소스 모듈(21)의 어휘, 구문 및 어의 분석을 행하고 ; 부록에 기재된 GEM$ST 및 GEM$1L 루우틴을 사용하여 상술한 모듈에 대한 심볼 테이블(30) 및 중간 언어 그래프(55)를 발생한다.
아울러, 모듈의 소스 리스트는 GEM$LS 셀 패키지에 대한 호출로써 주석이 붙여질 수도 있고, 모듈내에서의 에러는 GEM$MS 패키지에 대한 호출로써 보고될 수도 있다.
소스 모듈(21)이 코드 발생을 막기에 충분한 심각한 에러를 포함한다면, 전단(20)은 이제 리스팅 파일을 작성하기 위해 GEM$LS_WRITE_SOURCE를 호출하여야 하며, 그리고 내부적 표시(22)를 위해 할당된 모든 스페이스를 해제하도록 GEM$ST_FINI를 작성하여야 한다. 그렇지 않다면, 전단(20)은 다음의 단계로 진행해야 한다.
2. 역호출 루우틴의 특정
후단(12)을 호출하여 모듈(21)을 번역하기 전에, 전단(20)은 후단(12)에 의해 호출될 루우틴의 어드레스와 함께 다음의 전역 변수를 초기 설정하여야 한다.
(1) GEM$ST_G_GET_NAME은 상술한 바와 같이 심볼 테이블(30)내의 심볼 및 블럭 노드의 명칭을 생성하게 될 루우틴의 어드레스로 초기 설정되어야 한다.
(2) GEM$SE_G 전역 변수는 후술한 바와 같이 소스 언어로 정의된 측면 효과 분석을 행할 루우틴의 어드레스로 초기 설정되어야 한다. 컴파일러는 전단(20)의 초기 개발시에 사용하기 적합한 측면 효과 루우틴의 소정의 집합을 제공하는데 그것은 GEM$SE_DEFAULT_IMPLEMENTATION을 호출함으로써 선택될 수 있다.
(3) GEM$ER_G_REPORT_ROUTINE은 후술한 바와 같이 후단 검출 에러를 보고하기 위한 전단의 루우틴의 어드레스를 포함한다.
3. 번역의 수행
내부적 표시가 완성될 때, 전단(20)은 GEM$CO_COMPILE_MODULE(이하에서 설명)를 호출하여 그것을 타겟 머신 목적 표시(23)로 변환시킨다. 이어서 전단은 GEM$LS_WRITE_SOURCE를 호출하여 리스팅 파일에 입력 스티림을 리스트한다. 또한 GEM$LM_LIST_MACHINE_CODE를 호출하여 번역 모듈(23)의 어셈블리 코드 리스팅을 생성한다.
정상적으로 GEM$LS_WRITE_SOURCE는 GEM$CO_COMPILE_MODULE 후에 호출되어야 하므로 소스 리스팅(21)은 후단 처리시 발생된 어떤 에러 메세지로써 주석이 붙여질 수 있다. 그러나, 전단(20)이 먼저 GEM$LS_WRITE_SOURCE가 호출되게 할 디버깅 스위치를 제공하는 것은 좋은 아이디어이다. 이것은 버그(bug)가 후단 처리시 컴파일러로 하여금 동작 중지시키더라도 소스 리스팅을 얻을 수 있게 한다.
4. 클린 업(Clean Up)
번역이 완료될 때, 전단(20)은 GEM$CO_COMPLETE_MODULE을 호출하여 후단처리 동안 사용된 스페이스를 해제하여야 하고 이어서 GEM$ST_FINI를 호출하여 내부적 표시를 위해 사용된 스페이스를 해제하여야 한다.
후단(12)은 초기화되지 않은 변수, 도달될 수 없는 코드 또는 정적 기억장치 초기화의 충돌과 같은 사용자에게 보고되어야 하는 소스 프로그램(21)의 조건을 표시하게 되는 번역시 조건을 검출할 수 있다. 그러나, 특정 전단(20)은 이들 조건중 어떤 것이 보고될 것인지의 여부, 또는 반송된 정확한 메세지를 주문하는 것이 필요할 수도 있다.
이를 위해, 후단(20)은 어드레스가 전역 변수로 된 루우틴 GEM$34_G_REP ORT_ROUTINE 내에 있는 루우틴을 후술될 인수 리스트와 함께 호출함으로써 검출하는 모든 비정상 조건을 보고한다. 이 루우틴은 실제로 에러 메세지를 발송하는 역할을 한다.
GEM$ER_REPORT_ROUTINE이라 명명된 부록에 기재된 생략성 에러 보고용 루우틴이 존재하는데 그것의 어드레스는 전단이 거기에 독자적인 보고 루우틴의 어드레스를 저장하지 않은한 GEM$ER_G_REPORT_ROUTINE 내에 있을 것이다. 이 생략성 루우틴은 다음의 세가지 사용 상태를 갖는다.
(1) 생략성 루우틴은 올바른 메세지를 제공하므로, 전단 개발자(front end developer)는 그들이 독자적인 루우틴을 주문할 필요가 없는 한 그것을 제공하지 않아도 된다.
(2) 전단 개발자가 보고 루우틴을 기입하는 것을 선택할 때, 그들은 생략성 루우틴을 하나의 모델로서 사용할 수 있다.
(3) 전단의 루우틴은 어떤 에러 자체를 처리(또는 무시)하고 또 생략성 루우틴을 모든 다른 루우틴과 함께 호출하는 필터로써 기입될 수 있다.
[효과를 표시하기 위한 인터페이스]
공통 부표현(CSE), 불변표현 및 코드 액션을 위한 기회를 검출하는데 있어 필수적인 단계로서, 후단(12)내의 옵티마이저(26)는 두개의 표현 튜플이 동일 값을 계산하도록 보장 받는 시기를 결정할 수 있어야 한다. 기본적 기준은 다음과 같은 경우 표현 B가 표현 A와 동일 값을 계산한다는 것이다.
1. A와 B가 동일 값을 리터럴에 대한 리터럴 참조이거나, 동일 CSE에 대한 CSE 참조이거나, 또는 동일 심볼에 대한 심볼 참조인 경우 ; 혹은
2. a. A가 루우틴의 시작으로부터 B로의 모든 제어흐름 경로상에서 평가되는 경우와, b. A와 B가 동일 연산자 및 데이타 타입을 갖는 경우와, c. B의 피연산자가 A의 대응 피연산자와 동일 값을 계산하는 경우 (명백히 순환적 정의)와, d. A의 평가부터 B의 평가까지 어떤 경로상에서 발생하는 어떠한 튜플도 B에 의해 계산된 값에 영향 주지 않는 경우.
제1도의 옵티마이저(26) 는 기준 1, 2a, 2b 및 2c를 자체로서 효과화시킬 수 있지만, 기준 2d는 번역중인 언어 즉 소스 모듈(21)의 언어의 어의에 관계된다.그러나 , 후단내의 컴파일러(12)는 언어 독립성을 가져야 하기 때문에, 필요한 정보를 제공하도록 전단(20)에 일반적 인터페이스가 제공된다. 한 튜플의 실행이 다른 튜플에 의해 계산된 값에 영향을 줄 수 있는 시기는 언제인가? 인터페이스(22)는 옵티마이저(26)로 하여금 이러한 질문을 할 수 있도록 하여야 하며, 컴파일러 전단(20)으로 하여금 그것에 답할 수 있도록 하여야 한다.
이 인터페이스(22) 배후의 모델은, 어떤 튜플들은 효과를 가지고 그리고 다른 튜플은 종속성을 가지는 것이다. 튜플이 하나 이상의 기억 장소의 내용을 변경시키는 경우 튜플은 효과를 갖는다. 튜플에 의해 계산된 값이 기억장소의 내용에 관계되는 경우 튜플은 기억장소에 대한 종속성을 갖는다. 따라서, 한 튜플의 실행은 다른 튜플이 관계되는 기억 장소를 수정하는 효과를 갖는 경우 다른 튜플에 의해 계산된 값에 영향을 줄수 있다.
어드레스 연산 및 간접 어드레싱의 결과가 주어지면, 일반적으로 튜플에 의해 액세스된 특정 기억 장소를 결정하는 것이 불가능하다.
실제의 인터페이스(22)는 옵티마이저(26)에 두가지 메카니즘을 제공한다. 이들은 직선 종속성 인터페이스 및 결과 분류 인터페이스이다.
직선 종속성 인터페이스에서는, 직선 코드의 종속성을 판별하기 위해 옵티마이저(26)가 전단(20)으로 하여금(1) 효과 스택상에 튜플들을 밀어 넣고 다시 그것을 꺼내도록 요구하고, 또 (2) 그것의 실행으로 특정 튜플에 의해 계산된 값이 영향받을 수 있는 효과 스택상의 최상의 튜플을 찾아내도록 요구한 것이다.
직선 메카니즘은 옵티마이저(26)가 흐름 경로의 임의의 세트를 통한 프로그램의 흐름에 의해 어떠한 효과가 발생할 것인지 계산할 필요가 있을 때에는 적합하지 않다. 이러한 상황에서는, 전단(20)이 각각 기억장소의 어떤 (아마도 비결정의) 세트를 표시하는 특정 수(초기에 128)의 결과 분류를 정의할 수 있게 된다. 효과 분류의 한 세트는 하나의 비트 벡터로 표시된다. 예를 들어, 효과 분류는 특정 변수로 명명된 기억장소, 수순 호출에 의해 수정될 수 있는 모든 메모리 기억 장소 세트, 또는 간접 참조(포인터 참조)에 의해 액세스될 수 있는 기억 장소 세트를 표시할 수도 있다.
효과 분류 인터페이스 경우는, 옵티마이저가 전단으로 하여금 (1) 특정 튜플에 의해 변경될 수 있는 기억장소들을 포함하는 효과 분류 세트를 계산하고, (2) 특정 튜플이 관계될 수도 있는 기억 장소를 포함하는 효과 분류 세트를 계산하도록 요구할 것이다.
이 효과 분류 인터페이스를 사용하여 옵티마이저는 각 기본 블럭에 대하여 그 기본 블럭내의 어떤 튜플에 의해 수정될 수 있는 기억 장소를 포함하는 효과 분류 세트를 표시하는 비트 백터(LDEF 세트라 일컬어짐)를 계산할 수 있다.
옵티마이저는 또한 전단으로 하여금(3) 특정 변수 심볼과 관련된 기억 장소를 포함할 수도 있는 효과 분류 세트를 계산하도록 요구한다.
이 정보는 분할 후보(split candidate)의 수명을 계산하도록 분할 수명 최적화 단계(추후 설명)에 의해 사용되다.
옵티마이저(26)는 이들 인터페이스를 다음과 같이 사용한다. 이들 인터페이스가 설치되는 이유는 후단(12)내의 옵티마이저(12)로 하여금 “A의 평가부터 B의 평가까지의 어떤 경로상에 발생하는 튜플이 B에 의해 계산된 값에 영향을 줄 수 없는 시기”를 판별할 수 있도록 하는 것이라는 사실을 상기하기 바란다. 만일 A와 B가 동일 기본 블럭내에 발생한다면 이것은 바로 “A와 B 사이의 튜플이 B에 의해 계산된 값을 변화시킬 수 없음”을 의미한다. 이것은 직선 종속성 인터페이스를 사용하여 쉽게 결정될 수 있다.
만일 A를 포함하는 기본 블럭이 B를 포함하는 기본 블럭을 좌우한다면(즉 루우틴 입력 노드로부터 B를 포함하는 기본 블럭까지의 모든 흐름 경로가 A를 포함하는 기본 블럭을 통과한다면), 옵티마이저는 기본블럭 X1,X2...Xn의 시리즈를 찾아내는데 여기서 X1은 A를 포함하는 기본 블럭이고, Xn은 B를 포함하는 기본 블럭이며, 각 X는 바로 X(i+1)를 좌우한다. 여기서 그 테스트는 두개의 파트를 갖는다.
1. A와 기본 블럭 X1의 끝 사이, 기본 블럭 Xn 의 시작과 B 사이, 혹은 B에 의해 계산된 값을 변경시킬수 있는 기본 블럭 X2,X3,...X(n-1)의 어느 것에도 튜플이 존재하지 않아야 한다. 이것은 직선 종속성 인터페이스를 사용하여 판별될 수 있다.
2. 기본 블럭 Xi 및 X(i+1)의 둘 사이에 B에 의해 계산된 값을 변경시킬 수 있는 튜플을 포함하는 흐름 경로가 존재하지 않아야 한다. 옵티마이저는 이것을 Xi 에서 X(i+1)까지의 어떤 흐름 경로상에서 발생하는 모든 기본 블럭의 LDEF 세트의 집합을 계산하고, B가 종속될 수도 있는 기억장소를 포함하는 결과 분류 세트와 이 세트와의 교집합(intersection)을 계산한 다음, 이 교집합이 비어있는지의 여부를 테스트하는 것에 의해 결과 분류 메카니즘으로써 테스트한다.
이하 인터페이스의 구조에 관해 설명한다. 인터페이스 루우틴은 후단 (12)에 의해 호출된다.전단(20)은 그것이 후단(12)을 호출하기 전에 이용될 수 있는 인터페이스를 실현할 수 있어야 한다. 전단은 인터페이스 루우틴 입력 지점의 어드레스를 표준 전역 변수로 둠으로써 이것을 행한다. 이어서 옵티마이저(26)는 이 루우틴중 하나를 호출할 때 적절한 전역 변수로부터 루우틴 어드레스를 적재할 수 있다. 인터페이스 루우틴은 형식 GEM_SE_XXX의 명칭으로 추후 기재된다. 전단은 GEM_SE_XXX 라는 명칭의 전역 변수로 된 각 대응 실현 루우틴의 입력 어드레스를 저장하여야 한다.
효과 및 종속성을 갖는 튜플들은 이 인터페이스에 중요한 것이다. 소수의 IL 튜플만이 효과 및 종속성을 갖는다(개략적으로,스토어를 행하는 튜플들은 효과를 가지고, 인출을 행하는 튜플들은 종속성을 가지며, 루우틴 호출을 행하는 튜플들은 양자를 가질 수 있다)
구체적으로, 각 튜플은 다음의 카테고리중 하나에 속한다.
1. 튜플이 어떤 효과를 갖지 않고 또한 효과에 대한 종속성도 갖지 않는다(예: ADD). 이 분류에 속하는 튜플들은 효과 스택상에 넣어지지 않으며, 그러한 튜플들은 결코 GEM_SE_EFFECTS로 통과되지도 않는다.
2. 튜플이 효과를 가질 수 있지만 종속성을 갖지는 않는다(예:STORE).
3. 튜플이 종속성을 가질 수도 있지만 어떠한 효과도 유발하지 않는다.(예:FETCH).
4. 튜플이 효과(외부 효과 : out-effects) 및 별도 세트의 종속성(내부 효과 : in-effects) 양자를 가질수도 있다(예 : 수순 호출)
5. 튜플이 효과 및 종속성 양자를 가질 수도 있다. 그것이 생성하는 효과와 동일하다.(예 : PREINCR). DEFINES 튜플이라 불리는 특정 튜플은 전단으로 하여금 어떤 튜플과도 관련되지 않는 효과를 특정하도록 하기 위하여 제공된다. DEFINES 튜플의 한가지 가능한 사용은 최적화가 허용되지 않는 장벽으로서 작용하는 BLISS CODE COMMENT 특징을 실현케 하는 것이다. CODECOMMENT의 변환은 모든 효과를 갖는 DEFINES 튜플로 되므로 모든 튜플을 무효화시킨다.
인수 통과용 튜플(예컨대 ARGVAL 및 ARGADR)은 효과 및 종속성을 갖는다. 그러나, 파라미터 튜플의 효과 및 종속성은 파라미터 튜플이 속하는 루우틴 호출과 관련되어 실제적으로 고려된다. 예를 들면, BLISS 루우틴 호출 F(X,.X+Y)에서, 파라미터 X는 X를 변경시키는 효과를 갖는다. 그러나, 이것은 X+Y의 이전에 계산된 값을 무효화시키지는 않을 것이며, 그 이유는 F 가 호출될 때까지 효과가 실제로 발생하지 않기 때문이다.
튜플을 나타내는 제4도의 데이타 구조는 전단(20) 및 후단(12) 양자에 의해 액세스되며, 이 구조의 어떤 필드들은 단지 전단 혹은 단지 후단 액세스로 제한된다. 효과 또는 종속성을 가질 수 있는 모든 튜플(35)은 전형적으로 GEM_TPL_XXX_ EFFECTS 또는 GEM_TPL_XXX_DEPENDENCIES라 명명된 하나 이상의 긴 워드(longword) 필드(42) 또는 (43)을 포함할 것이다. 특정 튜플에 사용된 필드 명칭은 「중간 언어」상의 섹션에 기재된다. 후단내의 코드는 이 필드들을 결코 검사 또는 수정하지 않을 것이다. 그들은 전단에 의해 사용을 위해 보존된다. 그들은 인터페이스 루우틴의 코드화를 간소화하는데 사용될 수 있는 정보를 기록하기에 편리한 장소가 된다. 심볼 테이블(30)의 각 심볼 노드에는 GEM_SYM_EFFECTS라 명명된 유사한 긴 워드 필드가 있는데, 그것 역시 전단(20)에 의한 사용을 위해 보존된다.
직선 종속성 인터페이스에 있어서, 이하 루우틴의 기재를 설명한다. 전단은 다음의 루우틴을 실현한다.
GEM_SE_PUSH_EFFECT(EIL_TUPLE : GEM_TUPLE_NODE에서)
어드레스가 EIL_TUPLE 파라미터인 EIL 튜플을 효과 스택상에 넣어라. GEM_SE_PUSH_EFFECT(EIL_TUPLE : GEM_TUPLE_NODE에서)-효과 스택으로부터 최상부 EIL 튜플을 팝(POP)한다. 이것은 어드레스가 EIL_TUPLE 파라미터내에 있는 튜플이 되도록 보장된다. 물론 이것은 파라미터가 용장성임을 의미한다. 그러나, 이것은 효과 스택에 대한 단일 스택 실시를 사용하지 않는 전단에 대한 POP 절차의 코딩을 단순화한다(이하의 실시예 설명 참조)
GEM_PUPLE_NODE=
GEM_SE_FIND_EFFECT(
EIL_TUPLE : GEM_TUPLE_NODE에서,
MIN_EXPR_COUNT : 값)
GEM_TPL_EXTR_COUNT필드가 MIN_EXPR_COUNT(하기 참조)보다 더 크고 그 실행이 EIL_TUPLE에 의해 산출된 효과를 변경시킬 수 있는 가장 최근에 푸쉬된 튜플을 복귀시킨다. 스택상의 어떠한 튜플도 EIL_TUPLE에 영향을 끼치지 않는다면, 영(제로)을 복귀시킨다. 파라미터에 의해 특정된 동일한 튜플을 또한 복귀시킬 수 있다.
GEM_TUPLE_NODE=
GEM_SE_FIND_EFFECT(
VAR_SYM : GEM_SYMBOL_NODE에서,
MIN_EXPR_COUNT : 값)
GEM_TPL_EXTR-COUNT 필드가 MIN_EXPR_COUNT(하기 참조)보다 더 크고 그 실행이 가변성 VVAR_SYM의 값을 수정할 수 있는 가장 최근에 푸쉬된 튜플을 복귀시킨다. 스택상의 튜플이 EIL_TUPLE에 영향을 주지 않으면 널(null : 제로)을 복귀시킨다. 또한, 파라미터에서 지정된 동일한 튜플을 복귀시킬 수도 있다.
GEM_SE_PUSH_EFFECT 및 GEM_SE_POP_EFFECT는 효과를 갖는 튜플과 함께로만 호출된다. GEM_SE_FIND_EFFECT는 종속성을 가질 수 있는 튜플과 함께로만 호출된다.
여기에는 실시의 순서가 있다. 각 EIL 튜플은 GEM_TPL_EXPR_COUNT라 하는 필드를 갖는다. 이 필드는, 기본 블럭이 도미네이터 트리 깊이-제1 프리오더(dominator tree depth-first preorder)에서 유도되는 EILG의 행보의 튜플 인덱스를 포함한다. 후단(12)이 튜플 A로써 GEM_SE_PUSH_EFFECT를 호출하면, 그리고 중간에서 튜플 A로써 GEM_SE_POP_EFFECT를 호출함이 없이 튜플 B로써 GEM_SE_PUSH_EFFECT 또는 GEM_SE_FIND_EFFECT를 연속적으로 호출하면, 튜플 A가 동일한 기본 블럭에서 튜플 B를 앞서거나 튜플 A를 포함하는 기본 블럭이 튜플 B를 포함하는 기본 블럭을 적절히 지배하는 것이 보장된다. 그러므로 효과 스택상의 튜플의 EXPR_COUNT 값은 스택 깊이의 증가에 따라 감소한다.(즉, 보다 최근에 푸쉬된 튜플들은 보다 덜 최근에 푸쉬된 튜플들보다 더 높은 EXPR_COUNT를 갖는다). 이것은 FIND_EFFECT 루우틴이 EXPR_COUNT가 MIN_EXPR_COUNT 인수(argument)보다 더 적거나 동일한 튜플 T와 만나자마자 효과 스택의 조사를 짧게 단축할 수 있다는 것을 의미한다. 이것은 T보다 더 깊게 스택된 모든 튜플들이 MIN_EXPR_COUNT보다 더 적은 EXPR_COUNT들을 갖는 것이 보장되기 때문이다.
효과 스택을 실시하는데 실제로 사용되는 메카니즘은, 하나의 튜플의 실행이 다른 튜플에 의해 계산된 값에 영향을 줄 가능성이 있을 때를 결정하는데 사용되는 것이 규칙이므로, 완전히 전단(20)까지이다. 순수한 스택 실시는, 비효과적일 사능성이 있다 할지라도, 확실히 가능하다. 보다 복잡한 실시가 해쉬 테이블(hash table) 부근에서 이룩될 수 있으며, 따라서 복수의 작은 스택들(각각이 단지 하나 또는 수개의 변수와 관련될 수 있음)을 하나의 큰 스택 대신에 사용할 수 있다.
이제 효과 클래스 인터페이스에 대하여 설명한다. 효과 세트가 한 세트의 효과 클래스를 나타내는 비트 벡터이고 효과 클래스가 어떤 임의의 메모리 위치 세트를 나타냄을 상기한다. 일반적으로 효과 클래스는 이하의 것중 하나를 나타낸다.
1. 단일명의 변수. 효과한 최적화를 위하여, 루우틴에서 빈번하게 사용되는 각각의 단순한(즉, 분산된) 로컬 변수는 그것에 부여된 효과 클래스를 가져야 한다.
2. 어떤 공통 특성을 갖는 한 세트의 명명된 변수; 여컨대, FORTRAN에서, 특정명의 공통 블럭내의 모든 변수.
3. 구동 시간까지 결정되지 않을 수 있지만 어떤 공통의 특성을 갖는 한 세트의 메모리 위치 ; 예컨대 이 루우틴의 외측에서 볼 수 있는 모든 메모리 위치(따라서 이것은 루우틴 호출에 의해 수정될 수 있음) ; 또는 파스칼에서 새로운 흘출로 동적 할당되고 특정한 형태를 가질 수 있는 모든 메모리 위치.
문자 GEM_SE_K_MAX_EFFECTS는 GEM_SE 패키지에 의해 이출(export)된다. 이것은 전단(20)을 규정할 수 있는 별개의 효과 클래스의 최대수이다. 이것은 초기 실시예에서 128일 수 있다. GEM_SE_EFFECTS_SET 형은 GEM_SE 패키지에 의해 이출된다. 이것은 BITVECTOR[GEM_SE_K_MAX_EFFECTS]까지 연장하는 대량이다. 따라서, 선언(declaration) X : GEM_SE_EFFECTS_SET가 주어지면, 이하의 구성은 매우 자연스럽다(여기에서 0≤N≤GEM_SE_K_MAX_EFFECTS -1) :
X(N)=참(true) ! 효과 클래스 N을 세트 X에 부가.
X(N)=거짓(false) ! 세트 X로부터 효과 클래스 N을 제거
X(N)이면… ! 효과 클래스 N이 세트 X내에 있으면…
이제 효과-클래스 인터페이스에 대한 인터페이스 루우틴을 설명한다. 전단(20)은 하기 루우틴의 실시를 제공하여야 한다.
GEM_SE_EFFECTS(
EIL_TUPLE : GEM_TUPLE_NODE내,
EFFECTS_BV : GEM_SE_EFFECTS_SET외)
튜플 EIL_TUPLE 및 EFFECTS_BV의 효과의 결합은 EFFECTS_BV내로 기록된다.
GEM_SE_DEPENDENCIES(
EIL_TUPLE : GEM_TUPLE_NODE내,
EFFECTS_BV : GEM_SE_EFFECTS_SET외)
EIL_TUPLE이 EFFECTS_BV에 의존하는 효과 클래스의 세트를 기입한다.
GEM_SE_VARIABLE_DEPENDENCIES(
SYMBOL : GEM_SYMBOL_NODE내,
EFFECTS_BV : GEM_SE_EFFECTS_SET외)
변수 SYMBOL과 관련된 메모리를 포함할 수도 있는 효과 클래스의 세트를 EFFECTS_BV내에 기입한다.
GEM_SE-EFFECTS는 효과를 가질 수 있는 튜플과 함께만 호출된다. GEM_SE_DEPENDENCIES는 종속성을 가질 수 있는 튜플과 함께만 호출된다.
컴파일러는 상기 언급한 인터페이스 루우틴에 대한 실시를 제공할 수 있지만, 이 루우틴들은 생산 컴파일러에서 사용하고자 하는 것은 아니다. 이들은 무효하고, 하나의 튜플이 다른 것을 무효화하게 되는 그들의 규칙들은 어떤 특정 언어의 의미론(Semantics)과 정확히 일치하지 않을 수도 있다. 그러나 이들은 전단(20)의 다른 성분들이 실시될 때 유용한 생략성 최적화(default optimization)가 발생되게 한다.
각 심볼 노드의 EFFECTS 필드는 32와 GEM_SE_K_MAX_EFFECTS 사이에서 효과 클래스 번호로서 처리된다. 인출 또는 기억 튜플의 어드레서 표현이 베이스 심볼을 가질 때, 그 심볼의 EFFECTS 필드가 체크된다. 이것이 만일 제로이면 이것은 32와 GEM_SE_K_MAX_EFFECTS 사이의 새로운 값으로 세트된다.
상기한 효과 클래스 실시를 사용하여 효과 세트들을 계산하기 위하여, 전단은 GEM-IL_BUILD 페이즈를 호출하기 전에 GEM_SE_INIT_EFFECTS_CLASSES를 호출하여야 한다.
이 실시는 효과에 대한 간단한 모델을 규정함으로써 효과에 대한 정보를 제공한다.
1. 변수들이 오버레이(overlay)되지 않는다.
2. 표준적인 형태(CT.006에 규정됨) 이외의 형태인 데이타 액세스 동장은 (기억을 위해) 효과 0을 갖거나(인출을 위해) 효과 0에 의존하다.
3. 호출들은 효과 32 내지 GEM_SE_K_MAX_EFFECTS를 갖는다. ARGADR 파라미터는 마치 호출이 그 어드레스 피연산자내에 기록된 것처럼 처리된다.
효과 클래스 0과 32내지 GEM_SE_K_MAX_EFFECTS는 보존된다. 효과 0는 인용되는 변수들이 확인될 수 없도록 메모리에 대한 참조들을 나타낸다(포인터 디레퍼런스(dereferences), 파라미터, 등).
변수가 표준적인 형태의 데이타 액세스 연산자를 사용하여 최초로 인용될 때 그 변수에는 32내지 GEM_SE_K_MAX_EFFECTS의 범위내에서 효과 클래스 번호가 할당된다. 이 번호는 심볼 노드의 효과 필드내에 기록된다. 그 변수에 대한 인용 및 모든 후속 인용들은 효과 또는 종속성(dependency) n을 갖는다.
실시는 실험, 테스팅 등을 위한 몇가지 후크(hook)를 포함한다.
1. 효과 또는 종속들을 가질 수 있는 튜플들은 튜플의 효과 및 종속을 기록하기 위하여 전단에 보존된 한개 이상의 “효과 필드”(EFFECTS, DEPENDENCIES, EFFECTS_2, 등)를 구비한다. 컴파일러에 의해 공급된 효과 클래스 역호출들은 GEM_SE_EFFECTS_SET의 제1워드를 나타내는 길이 32의 비트 벡터로서 효과 필드를 해석한다. 즉, 필드의 비트 n이 참이면 루우틴은 효과 클래스 n을 튜플의 계산된 효과에 부가한다.
2. 전단은 1과 GEM_SE_K_MAX_EFFECTS의 사이의 효과 클래스 번호를 변수의 심볼 노드의 효과 필드에 기록함으로써 변수에 대한 효과 클래스를 선정할 수 있다. 효과 클래스 루우틴은 효과 필드가 제로가 아니면 효과 클래스를 할당하지 않는다.
3. 효과 클래스 1∼32는 전단에 의한 사용을 위하여 보존된다. 이것은 효과 클래스에 대해 어떤 해석을 할당할 수도 있다.
상기한 직선 종속 실시를 사용하기 위하여, 전단은 GEM_DF_DATAFLOW 페이즈를 호출하기 전에 GEM_SE_INIT_EFFECTS_STACK를 호출하여야 한다. 이 실시는 무효성을 결정하기 위하여 GEM_SE_EFFECTS를 GEM_SE_DEPENDENCIES 역호출에 의해 제공된 정보를 사용한다. 즉, GEM_SE_FIND_EFFECT(X)는 GEM_SE_EFFECTS(Y) 및 GEM_SE_DEPENDENCIES(X)가 무효로 되지 않도록 가장 최근에 푸쉬된 튜플 Y를 복귀시킨다.
[유도 변수]
본 발명의 한가지 특징에 따르면, 컴파일러에서 유도 변수를 처리하는 개선된 방법이 제공된다. 먼저 유도 변수 및 수식의 정의 및 검출에 대하여 설명한다.
정수 변수 V는 루우프 L에서 발생하는 V에 대한 각각의 기억이 하기의 경우에 있을 때에 루우프 L의 유도 변수라고 말하여진다.
1. V가 실행될 때마다 동일한 크기 만큼 V를 증가(또는 감소)시킨다.
2. 루우프를 통한 “완결된 트립(complete trip)”마다 많아야 1회씩 실행된다.
트립은 루우프 상단으로 돌아가면 “완결”된다. 예컨대, 하기의 코드는 유도 변수 V를 설명한다 :
라벨 L V=1
IF V > 10
GOTO LABEL M
ELSE
PRINT X
V=V+1
END IF
컴파일 기능에서, 유도 변수를 찾는 것 외에, 유도 수식을 찾는데에도 또한 관심이 있다. 유도 수식은 유도 변수의 선형 함수로써 계산될 수 있는 수식이다.
하기의 프로그램을 생각한다.
DO I=1,100
X=I*8
T=I-4
A[I]=T*4
END DO
수식 “I*8”, “I-4”, “T” 및 “T*4”는 모두 이들이 I의 선형 함수로써 계산될 수 있다는 점에서 유도 수식이다.
유도 변수에 기초한 몇가지 최적화의 간단한 설명으로써 하기의 프로그램 예를 생각한다.
I=1 ;
L : X=X+(4*I)
I=I+1
if I<=100 GOTO L
이것은 간단한 DO 루우프이고, I는 루우프 제어 변수이다. 유도 수식 I*4는 루우프를 통한 각 트립시에 4씩 증가한다는 것을 주의한다. 새로운 변수 I2를 도입함으로써 승산을 가산으로 대체할 수 있는데 이것은 비용이 더 적게드는 동작이다. 이것은 장시간 동안 컴파일러를 최적화하는데 사용되는 강도 저하로써 알려진 최적화이다.
I=1 ;
12=4 ;
L : X=X+I2
I=I+1
I2=I2+4
if I<=100 GOTO L
앞에서는 한개의 변수를 가졌지만 이제 우리는 두개의 변수(I와 I2)를 가지게 된다. 원래의 루우프 제어 변수는 I2의 항에서 I를 사용할 수 있도록 다시 계산(recast)함으로써 완전히 제거될 수 있다.
I2=4 ;
L : X=X+I2
I2=I2+4
if I2<=400 GOTO L
이러한 최적화는 유도 변수 제거로써 알려져 있다.
이러한 최적화(강도 저하 및 유도 변수 제거)는 유도 변수상에서 직접 동작한다. 이러한 최적화외에, 유도 변수 검출은 자동 -inc/dec, 벡터화, 루우프 언롤링(loop unrolling), 등과 같은 다른 최적화에 정보를 제공한다.
제1도의 컴파일러에서 사용된 모델에서, 유도 변수는 루우프중에 1회 이상 증가시킬 수 있다. 또한 변화의 수는 각 반복시마다 다를 수 있다. 사실상, 변화의 수는 특정 반복에서는 제로일 수 있다. 루우프 불변 증가 값은 개개의 기억 사이에 차이가 있을 수 있지만, 각각의 기억은 그것이 실행될 때마다 동일한 크기로 변수를 증가시켜야 한다.
기본 유도 변수, 유도 수식, 및 의사 유도 변수를 포함한, 다른 특성들을 갖는, 유도 변수에는 몇가지 다른 카테고리가 있다.
기본 유도 변수들은 가장 간단한 형태의 유도 변수이다. 이들은 루우프 전체에 걸쳐서 적용되는 공지의 특성들을 갖는다. 모든 다른 유도 변수 및 수식들은 항상 기본 유도 변수의 선형 함수로써 만들어진다. 기본 유도 변수들은 일반적으로 I=I+q 또는 I=I-q의 형태로 수정되며, 여기에서 q는 루우프 불변수이다. 그러나 보다 일반적으로 말하면, 배정이 I=f(I)의 형태로 될 필요가 있으며, 여기에서 f(I)는 1개의 계수를 갖는 I의 선형 함수이다.
부록에서 주어진 알고리즘에서, 특징 루우프의 기본 유도 변수는 루우프 상단의 세트에 의해 표시된다. 이 세트 이외에, 우리는 또한 루우프를 통한 모든 트립에서 실행될 수는 없는 조건부 기억을 갖는 루우프에서 기본 유도 변수의 세트를 유지한다. 이것은 벡터화를 금지시키며 강도 저하를 소망하는 만큼 이룩할 수 있다.
유도 수식은 유도 변수에 대한 참조이거나 다른 유도 수식의 선형 함수이다. 유도 수식들은 하기 형태들 중 한가지이어야 한다.
f(I)
f(I)+g(I) f(I)-f(I)
f(I)+E E+f(I)
f(I)-E E-f(I)
f(I)*E E*f(I)
여기에서 f(I)와 g(I)는 루우프 L과 관련하여 기본 유도 변수 I로부터 유도된 유도 수식이고 E는 루우프 L의 불변수이다. 만일 f(I)와 피연산자인 산술 연산자 사이의 I에 기억이 없으면 산술 연산자는 루우프 L과 관련하여 기본 유도 변수로부터 유도된 유도 수식이다.
다른 카테고리는 의사 유도 변수이다. 어떤 조건하에서, 변수는 루우프를 통한 제1트립을 제외한 모든 트립상에서 마치 유도 변수처럼 작용할 수 있다. 이들은 최초의 루우프 반복을 필링(peeling)함으로써 유도 변수로(그리고 이로써 벡터화로)될 수 있다, 이러한 변수들은 “의사 유도 변수”라고 한다. 이것은 루우프내의 인출가, 하나의 기억은 추론된 유도 변수를 정의하는 루우프내에 있고 다른 하나의 기억은 그 값이 루우프 상단을 통해 흐르는, 2개의 기억에 의해서만 달성될 때 발생한다.
예를 들어서 ;
D=50
DO I=1, n
A[I]=D+…
D=I+4
루우프를 통한 제1트립에서, D는 I에 배정시 값 50을 갖는다. 후속 트립에서, D는 값 5,6,7 등을 갖는다. 루우프를 1회 언롤링함으로써 후속 트립들은 벡터화될 수 있다. 여기에 주어진 알고리즘은 의사 유도 변수인 유도 변수를 찾지 못한다는 것을 주의한다.
기본 유도 변수를 식별하기 위하여 컴파일러는 그것에 대한 모든 기억들을 인식할 수 있어야 한다. “별명화된 기억(aliased stores)을 가짐” 속성이 없으면 이것이 보장되고, 따라서 우리는 단지 “별명화된 기억을 가짐”을 갖지 않는 기본 유도 변수를 인식한다.
기본 유도 변수를 검출하는데는 잠재적인 유도 변수의 세트를 사용할 필요가 있다. 각 루우프에 대하여 이것을 동적으로 행하는 것은 비용이 많이들고 복잡한 동작이다. 그 대신, 우리는 IDEF 세트를 구성하는데 사용된 측면 효과 세트를 사용한다.
변수 “X”는, X의 인출(fetch)가 의존하는 모든 효과들이 S내에 있을 경우, IDEF 세트 S내에 있다고 말하여진다. 즉, X는 GET_VARIABLE_DEPENDENCIES( x)가 S의 서브 세트인 경우에만 IDEF 세트 S에 존재한다.
기본 유도 세트내의 X의 존재는 하기의 사항만을 암시한다.
(a) X는 기본 유도 변수이다. 또는 (b) X는 루우프 불변수이고, 기본 유도 변수인 최소한 1개의 변수와 함께 IDEF 비트를 공유한다.
부록에서의 알고리즘 설명은 알고리즘 설명을 간단히 한다는 관점에서 하기의 자유(liberty)를 취한다 :
(1) 선형 함수의 상수 부분의 축적은 오버 플로우를 일으킬 수 없다. (2) 모든 기억들은 변수를 완전하게 다시 규정한다.
부록에서 설명되고 있는 알고리즘은 루우프에서 수정된 모든 변수들이 기본 유도 변수라고 가정함으로써 시작한다. 각 루우프 상단은 기본 유도 변수 세트를 갖는다. 우리가 기본 유도 변수에 대한 요구 조건을 만족시키지 못하는 기억들을 찾았을 때, 우리는 루우프 상단의 기본 Ⅳ 세트로부터 변수들을 제거한다.
유도 수식 및 유추된 유도 변수들이 항상 기본 Ⅳ의 함수이므로, 우리는 기본 Ⅳ의 인출이 유도 수식의 원자 형태이라고 말한다. 즉, 수식이 유도 특성을 가지므로 수식은 유도 피연산자를 갖거나 또는 기본 유도 변수의 인출이다.
앞에서 주어진 규칙을 사용하여, 우리는 기본 Ⅳ에 대한 가정에 기초하여 더 간단한 유도 수식으로부터 유도 수식들을 만든다. 유도 수식의 기본 Ⅳ는 항상 수식과 함께 유지된다. 따라서, 알고리즘이 구동된 후에 우리는 수식이 유추되어지는 기본 Ⅳ가 아직 루우프의 기본Ⅳ세트에 있는지를 확인하기 위하여 검사함으로써 수식이 정말로 유도성인지 여부를 말할 수 있다.
부록에서 주어진 FIND_IV 알고리즘은 제1의 도미네이터 트리 워크인 DATAFLOW 페이즈의 일부로 된다. 하기 내용은 수행되는 튜플 처리의 개관이다 :
TUPLE[OPCODE] 선택
[FETCH]
만일 기본 심볼이 아직 기본 Ⅳ 후보자이면, 이 튜플을 유동성인 것으로 표시함.
[STORE]
V는 기억의 기본 심볼인 것으로 한다.
만일 기억되고 있는 값이 유도성이 아니면, 또는 기억되는 유도성 값의 기본 Ⅳ가 V가 아니면, 또는 기억된 값의 계수가 1이 아니면, 루우프 상단의 기본 Ⅳ 세트로부터 V를 제거하고, 루우프 상단의 기본 Ⅳ세트로부터 V를 제거하고, 기억을 유도성인 것으로 표시함.
[ADD,SUB,MUL, 등]
만일 한개의 피연산자가 유도성이고 다른 피연산자가 루우프 불변수이면, 이 튜플을 유도성인 것으로 표시함.
튜플 데이타 구조에 부가된 필드 및 흐름 노드에 부가된 필드는 유도 변수검출을 제공하기 위하여 표 6a에서 설명된다.
[K 폴드(KFOLD) 루우틴의 자동 발생]
앞에서 설명한 바와 같이, 제1도의 프로그래밍 언어는 컴파일러는 소스 언어로 기록된 프로그램을 타겟 머신(25)의 기계어로 번역한다. 컴파일러는 컴파일되는 모듈(21)내에 소스 언어의 놀리지(knowledge)를 통합시키는 전단(20)과 타겟 머신(25)의 기계어의 놀리지를 통합시키는 후단(12)를 포함한다. 전단은 프로그램을 소스 언어로부터 ILG(55)의 중간 언어로 번역하고, 후단은 프로그램을 중가 언어로부터 타겟 기계어로 번역한다.
중간 언어는 일반적으로 연산자의 수집(예컨대, 가산, 시프트, 비교, 인출, 기억 또는 탄젠트), 데이타 형태의 수집(예컨대, “부호화 32비트 정수”, “IEEE S-포맷 부동 소수점”, 또는 “문자 스트링”) 및 그러한 데이타 형태의 값에 대한 표시를 지정한다.
옵티마이저(26)에 포함된 최적화들중 하나는 상수 수식 평가 루우틴이다. 상수 수식에 관련되는 소스 코드 리스팅의 일예는 제6도에 도시되어 있으며, 여기에서 A와 B는 상수이고 따라서 A+B도 상수이며 이에 따라 I와 J는 같은 상수로 동일하다. 컴파일러는 (A+B)를 계산하고, 구동 시간에서 A와 B의 인출을 개별적으로 세이브할 뿐만 아니라 ADD 동작을 세이브한다. 따라서 제6도의 코드의 I=A+B와 J=A+B 수식은 단순히 STORE #9, I 또는 STORE #9, J로서 표시된다. 이것은, 상수들이 검출되고, 컴파일 시간에 계산되며 그리고 목적 코드 이미지내로 중첩되기 때문에, “상수 중첩”이라고 알려저 있다. 이것을 행하기 위한 메카니즘은 옵티마이저(26)의 일부분이며 K 폴드 루우틴이라고 한다.
제1도의 컴파일러는 이들 상수식을 찾아내기 위한 중간 언어의 수식을 평가하기 위한 K 폴드 루우틴을 통합한다. 일반적으로, 중간 언어의 연산자 및 그 피연산자의 값들이 주어질 때, 이 루우틴은 이 값들에 인가될 때 그 연산자에 의해 계산되는 동일한 값을 생성한다. 그러한 상수식 평가 루우틴은 컴파일러에서 많은 응용을 갖는다. 예를 들면,
(a) 프로그래에 대해 발생된 머신 코드의 실행 속도는, 프로그램이 실행될 때 보다는 프로그램의 일부 수식들이 컴파일러 그 자체에 의해 평가될 수 있을 경우에 개선될 수 있다.
(b) 일부 소스 언어는 상수 값을 나타내기 위하여 수식을 상수 피연산자와 함께 사용하게 할 수 있다. 그러한 언어의 프로그램을 컴파일하는 것을 컴파일러에 의해 그 수식들을 평가할 것을 필요로 한다.
(c) 중간 언어에서 제공된 동작의 레퍼토리가 프로그래밍 언어에 의해 제공된 동작 세트 또는 컴파일러가 실시되는 환경보다 더 풍부한 경우, 컴파일러에서 어떤 계산을 수행하는 가장 편리한 방법은 그 레퍼토리를 중간 언어의 수식으로 표현하고 그것을 상수식 평가 루우틴으로 전송하는 것이다.
상수식 평가 루우틴의 실행은 상당히 어려운 문제일 수 있다. IL은 수십개의 동작(예컨대, ADD, SUBT, COSINE, 등)을 가질 수 있고, 다른 데이타 형태(예컨대, INT32, NINT64, FLOATA, 등)를 생각할 때 중간 언어는 수백 또는 수천개의 다른 연산자를 가질 수 있다. 평가 장치는 각 데이타 형태에 정확히 각 동작들을 적용시킬 수 있어야 하며, 그렇지 않으면 컴파일러는 그 기능을 완전하게 그리고 정확하게 수행하지 못한다. 특히 부동 소수점 형태가 관련될 때에는 중간 언어로 표시되는 모든 동작들이 컴파일러가 실행하는 프로그래밍 언어에서 직접 이용할 수 없게 될 수도 있다. 결국, 상수식 평가 루우틴은 수백개의 다른 경우를 포함하여 극히 길어질 수 있고 에러 발생율이 높다.
본 발명의 일실시예의 중요한 특징에 따르면, 중요한 것은 중간 언어의 연산자의 정확한 의미가 항상 간결하고 정확하게 지정될 수 있는 하나의 언어가 중간 언어 그 자체라는 점이다. 즉, 컴파일러 후단 그 자체는 중간 언어의 어떤 연산자를 정확히 실시하는 코드를 발생할 수 있어야 한다. 다시말하면 이것은 컴파일러 후단이 이미 각 중간 언어 연산자의 효과를 실현하는데 필요한 일련의 머신 코드 명령들의 놀리지를 실시하며, 이 동일한 놀리지를 다시 상수식 평가 루우틴의 다른 형태로 코드화해야 하므로 용장성이 있다는 것을 말한다.
이 개념에 기초하여, 본 발명에 따르면, 상수식 평가 루우틴의 기계적 발생은 간단하게 된다. 제1단계는 제1도의 새로운 컴파일러를 창조하는 것인데, 이것은 정규 컴파일러로서 동일한 후단(12)을 사용하지만 그 전단(20)는 후술되는 특수한 전단으로 교체된다(등가적으로, 후술되는 바와 같이 동작하는 컴파일러용 특수모드를 제공한다).
두번째로, 특수한 전단(20) 또는 특수한 동작 모드는 소스 프로그램(21)을 판독 및 번역하지 않는다. 그 대신 다음과 같이 상수식 평가 루우틴을 위한 중간 언어를 발생한다.
(a) 루우틴은 인수 리스트내의 지정된 중간 언어 연산자에 기초한 경우를 선택하도록 조건 브랜치를 갖는다.
(b) 각각의 경우는 단일 연산자에 대한 코드를 포함한다. 루우틴의 인수 리스트로부터 피연산자 값들이 인출되고, 연산자를 그들에게 인가하고 그 결과를 복귀시킨다.
(c) 루우틴이 중간 언어로 직접 발생되기 때문에, 각 경우에 대한 코드는 인수 리스트로부터 피연산자를 인출하는 중간 언어 연산자, 그 다음에 특정한 경우를 위한 중간 언어 연산자, 및 그 다음에 그 결과를 복귀 시키는 중간 언어 연산자로 간단히 구성된다.
세번째로, 이 중간 언어 그래프가 컴파일러의 후단에 전송될 때 이 그래프는 상수식 평가 루우틴을 위한 머신 코드를 발생한다.
전술한 특수한 전단에서, 전단은 경우들이 발생되어야 하는 모든 연산자의 리스트를 포함할 수 있고, 각 경우에 대한 중간 언어를 기계적으로 발생할 수 있다.
그러나 처리는 종종 발생하는 바와 같이 컴파일 후단이 이미 연산자 정보의 표를 이미 포함하고 있으면 더욱 간단해질 수 있다(예컨대, 이러한 표는 전단에 의해 발생된 중간 언어 그래프의 정확성을 체크하기 위해 사용될 수 있다). 그 다음에는 특수한 전단이 어떤 경우가 발생되는지 결정하기 위하여 후단에 의해 이미 제공된 상기 표를 사용할 수 있다.
[타입 정의(type definition)]
제1도의 컴파일러는 GEM_TD 모듈이라고 하는 타입 정의 모듈을 사용한다. GEM_TD는 링커 또는 디버거에서 사용하는 목적 모듈에 통합되어질 프로그램 타입 정보를 구성함에 있어서 전단(20) 및 후단(12)에 의해 사용되는 메카니즘을 제공한다. 이 타입 지정 서비스는 전단(20)이 프로그램 심볼 및 타겟 목적 파일요구에 무관한 방법으로 목적 모듈 빌더(builder)(29)에 대한 관련 타입 정보를 묘사하게 한다. 이 타입 지정 서비스는 컴파일러가 추상적 타입 지정 및 프로그램 심볼을 통합할 수 있도록 절차적인 “타입 문법”으로서 동작한다. 타입 지정 인터페이스는 이후에 규정되고, GEM_TD 서비스의 사용이 많은 예가 참조된다.
타입 정보 생성은 심볼 테이블(30) 생성과 관련해서 발생하고, 전단(20)이 프로그램 타입 정보의 추상적 표시를 지정할 수 있게 한다. 목적 모듈 빌더(29)는 나중에 디버그 심볼 테이블 정보를 구성함에 있어서 이 정보를 사용한다.
GEM_TD 모듈은 전단(20)이 기본 타입 및 파생된 타입을 묘사하도록 하는 서비스 루우틴을 제공한다. 이 루우틴들은 전형적으로 지정 타입 정보를 묘사하는 내부 데이타 구조를 구성한다. 새로운 컴파일러 노드타입(GEM-TDI)은 이 타입의 정보를 관리하도록 정의될 것이다. 타입 노드 데이타 구조의 정의는 컴파일러(12)에 전용되고 전단(20)에 의해 변경되거나 시험되지 않는다. 타입을 정의할 때, 전단(20)은 타입을 정의하는 GEM_TD 루우틴에 의해 “핸들”을 그 타입 노드로 복귀시킨다. 핸들은 전단이 어떤 타입을 프로그램 심볼과 통합할 수 있게 하지만 전단이 데이타 구조의 필드를 변경시키거나 시험하는 것을 금지시킨다.
타입 노드는 범위(scope)에 의해 생성 및 관리되는데, 즉 타입 정보를 전송할 때 전단(20)은 타입이 선언되어질 블럭 노드를 지정하고 그리고 셀(shell)은 그 범위내에서 타입 노드를 관리할 책임을 갖는다. 셀은 타입이 규정되는 블럭 노드에 기초한 리스트내의 타입 노드를 관리한다. 블럭 노드 데이타 구조는 필드 TYPE_LIST_HEAD와 TYPE_LIST_TAIL을 규정하도록 확장된다.
전단(20)은 타입 지정 서비스 루우틴에 대한 온더 플라이(on-the-fly) 호출을 행할 것을 선택하거나, 타입 정보를 발생하기 위해 전체 심볼 테이블을 거치는 통과를 만들 것을 선택할 수도 있다.
타입 정의 후에, 전단은 이 타입 정보를 그 타입의 심볼과 연합시켜야 한다. 심블 노드는 심볼을 이 타입과 연합시키는데 사용되는 새로운 필드 DST_TYPE_INFO를 갖는다. 심볼의 DST_TYPE_INFO 필드는 GEM_TD 서비스에 의해 복귀된 타입 노드 핸들의 어드레스를 포함한다. 널의 DST_TYPE_INFO 값을 갖는 심볼 노드는 타입 정보를 갖지 않는 심볼에 대한 타겟 지정 작용을 갖는다.
제7도를 참조하면, 데이타 필드 및 관계가 하기의 함수에 대하여 설명된다.
int toy_procl)
{
float b,c ;
:
}
toy_proc에 대한 블록 노드(60)는 심볼 테이블(30)에서 엔트리(63,64,65)를 지시하는 필드(61,62)(decl 리스트 포인터)를 포함한다. 또한 이것은 int 및 플로트에 대한 타입 리스트의 엔트리(68,69)를 지시하는 타입 리스트 포인터로서 작용하는 필드(66,67)를 포함한다. 엔트리(63,64,65)는 또한 대부분의 경우와 같이 int 및 플로트에 대한 엔트리(68,69)를 지시하는 포인터(70,71,72)를 갖는다.
GEM_TD 타입 특정 서비스는, 전단(20)이 표준 및 파생된 타입을 규정하고 그 타입들을 프로그램 심볼과 연합시킬 수 있도록 하는 루우틴들로 구성된다. 컴파일러 후단(12)은 타겟 특정 디버그 심볼 테이블을 발생하도록 결과 타입 정의 및 그들의 심볼 노드 연합을 사용한다. 부울(boolean)은 기본 타입으로서 생각되지 않음을 주의한다. 파스칼과 같은 언어를 위한 컴파일러는 참 및 거짓의 요소들을 포함하는 목록으로서 부울을 규정하여야 한다.
[멀티 패스 코드 발생기용의 활동 언어(action language)]
이제 코드 템플리트(template)를 사용하여 코드 발생기(29)에 의해 후단(12)에서 코드 발생을 수행하는 방법을 설명한다. 코드 템플리트의 선택 및 응용은 컴파일 처리중에 4개의 상이한 시간에서 발생한다.
1. PATSELECT 페이즈는 최상의 코드 템플리트를 선택하기 위하여 CONTEXT 패스(pass)에서 패턴정합(pattern match)을 행한다(이 패턴 정합 과정중에 UCOMP 및 DELAY 최적화 과업(task)이 패턴 정합 처리의 일부로서 나란히 수행된다).
2. CONTEXT 패스의 TNASSIGN 및 TNLIFE 과업은, 수식에 대한 평가 순서를 분석하고 코드 템플리트에 비로컬(nonlocal)한 수명 시간을 TN에 할당하도록 선택된 템플리트의 문맥(context) 활동을 사용한다.
3. TNBIND 패스는 코드 템플리트에 로컬한 수명 시간을 TN에 할당하도록 선택된 템플리트의 바인딩 활동을 사용한다.
4. 마지막으로, CODE 패스는 목적 코드의 발생을 안내하도록 선택된 템플리트의 코드 발생 활동을 사용한다.
템플리트는 컴파일중에 다른 시간에서 사용된다. 이것은 3개의 주성분으로 구성된다.
1. ILG 패턴-이것은 템플리트를 응용 가능한 ILG 구조에 정합시키는 템플리트 선택 처리를 안내한다.
2. 비지연 활동-이것은 CONTEXT, TNBIND 및 CODE 패스중에 정합된 ILG 구조의 처리를 결정한다. 비지연 활동은 템플리트가 각 패스에서 최초로 처리될 때 수행된다. 그 결과, 각 ING 노드에 대한 템플리트 활동은 각 패스에 대해 1회씩 3개의 다른 시간에서 처리된다. 일부 활동들은 단지 하나의 패스에 대해서만 의미를 가지며 다른 패스에서는 무시된다. 다른 활동들은 1개 이상의 패스에서 의미를 갖지만 요구되는 처리는 각각의 패스마다 다르다.
3. 지연된 활동-이것은 또한 CONTEXT, TNBIND 및 CODE 패스중에 정합된 ILG 구조의 처리를 결정한다. 지연된 활동은 템플리트에 의해 계산된 결과가 다른 템플리트의 잎(Ieaf)으로서 최초 처리될 때 각 패스에서 수행된다. 지연될 활동은 어드레스 모드를 갖는 VAX와 같은 타겟 머신에서 유용한다. RISC와 같은 간단한 레지스터 머신은 아마 지연된 활동의 많은 사용을 행하지 않을 것이다.
코드 발생 템플리트의 ILG 패턴은 4편의 정보를 구성된다.
1. 템플리트의 발생된 코드에 의해 계산된 값의 표시를 코드화하는 결과치 모드(부록에 주어진 예 참조)
2. 이 템플리트에 의해 부호화될 수 있는 ILG 노드의 배열을 묘사하는 패턴 트리, 패턴 트리의 내부 노드는 IL 연산자이고, 패턴 트리의 잎들은 피연산자를 갖지 않는 IL 연산자 또는 값 모드 세트이다.
3. 일련의 부울 테스트. 이들 모두는 패턴을 응용할 수 있게 하기 위해 참으로 평가되어야 한다.
4. 이 템플리트에 의해 발생된 코드의 “코스트(cost)”를 나타내는 정수.
패턴 정합 또는 PATSELECT 페이즈는 ILG 서브트리를 템플리트의 패턴과 정합시킨다. 1개 이상의 템플리트 패턴이 ILG 노드에서 응용될 수 있으면, 패턴 정합자는 어떤 것이 가장 낮게 평가되는 코드 코스트로 인도된다는 것을 인식할 때까지 다른 템플리트들 사이에서의 선정을 지연시킨다.
여기에서 3개의 다른 활동 해석기(interpreter), 즉 CONTEXT 해석기, TNBIND 해석기 및 CODE 해석기가 있다. 각 템플리트의 활동은 적당한 해석기에 의해 컴파일러의 3개의 상이한 패스에서 수행된다. 3개의 패스 모두에서 동일한 템플리트가 사용된다 하더라도, 활동의 의미론은 페이즈 종속성이며 따라서 상이한 일들이 각 패스에서 수행된다. 많은 활동들은 3개의 패스중 하나에서만 의미를 가지며, 이 활동들은 다른 두개의 패스에서는 아무것도 행하지 않는다. 다른 활동들은 1개 이상의 패스에서 의미를 갖지만, 1개 패스에서의 활동의 의미론은 종종 다른 패스에서의 동일 활동의 의미론과는 전혀 다르다. 그러나, 템플리트에서 단지 하나의 활동 시퀀스(sequence)를 갖는 것은 이해를 매우 쉽게 하고 또한 여러가지 패스 사이에서 종속성이 유지를 쉽게 한다.
각 템플리트에 대한 활동 시퀀스는 2개의 부분, 즉 비지연 활동과 지연 활동으로 이루어진다. 선택된 ILG 노드의 패턴이 최초 처리될 때에는, 비지연 활동이 해석된다. ILG 패턴이 다른 ILG 패턴의 잎으로서 나중에 사용될 때에는, 지연 활동이 해석된다.
비지연 활동의 해석 개시시에, 피연산자 변수의 표가 생성된다. 피연산자 변수는 임시명(TN), 즉 문자 또는 타겟 지정 어드레스 모드를 포함할 수 있다.
임시명은 각각 3개의 클래스, 즉 (1) 영구 TN, (2) 지연 TN 및, (3) 로컬 TN중 하나로 구분된다. TN의 클래스는 그 수명 시간 및 사용에 의해 결정된다.
각 TN은 할당 수명 시간을 가져야 한다. 할당 수명 시간은 적당한 템플리트 활동에 의해 시작되며, TN의 최후 사용으로 인도하는 모든 흐름 경로를 따라 연장한다. 영구 클래스의 TN들은 어떤 임의의 대량의 코드를 TN의 생성후에 미래에서 종결짓는 수명 시간을 가질 수 있다. 지연 클래스 TN의 수명은 템플리트의 지연 활동에서 시작하고 TN이 잎으로서 사용된 바로 뒤에 종결되어야 한다. 로컬 TN의 수명은 결코 단일 패턴의 해석을 넘어서 연장되지 않는다.
TN의 클레스는 그것이 어떻게 처리될 것인지를 결정한다. 영구 클래스 TN은 CONTEXT 패스에서 1회 생성되고, 동일한 TN 데이타 구조는 3개의 패스 모두를 통하여 유지되며 TN의 복잡한 수명 시간 묘사를 기억하기 위해 사용된다. 지연 클래스 및 로컬 클래스 TN은 매우 제한된 기간의 수명 시간을 갖기 때문에 이 정보를 추적하기 위해 영구 데이타 구조를 가질 필요는 없다. 그 결과, 지연 클래스 및 로컬 클래스 TN의 TN 데이타 구조는 활동들을 해석할 때 각 패스를 구성하고 또한 각 패스에서 최후의 사용후에 즉시 제거된다. 각 패스에서 동일한 활동 시퀀스가 해석되면, 이들 클래스의 TN에 대한 각 패스에서 동일한 TN 데이타 구조가 구성되는 것이 보장된다.
상이한 템플리트 활동의 대형 리스트가 있을 수 있다. 이들 활동중의 일부는 타켓 머신 종속성이다. 부록은 제안된 또는 예시적인 템플리트 활동의 리스트를 포함하고 있으며, 따라서 사용자는 이들 코드 템플리트 예들에 의해 특정 실시예에 대하여 무엇이 필요한지를 결정할 수 있다.
[중간 언어 표시]
제1도의 컴파일러 프레임워크(10)에서 사용된 내부 표시는 심볼 테이블(30) 및 중간 언어 그래프(55)를 포함하며, 이들은 소스 모듈(21)의 구조, 데이타 및 코드를 나타내도록 전단(20)에 의해 생성된 데이타 구조이다. 이하에서는 IL 그래프(55)에서 사용된 중간 언어 및 심볼 테이블(30)의 지정을 포함하여, 이들 데이타 구조의 원천적 성분인 노드를 설명한다. 제1도를 참조하여 설명된 컴파일러에서, 전단(20)은, 실행 가능한 코드를 기술하기 위해, 소스 모듈(21)에 포함된 프로그램의 블럭, 루우틴, 변수, 문자 값 등을 기술하는 심볼 테이블(30)을 발생하고 또한 하나 이상의 중간 언어 그래프(55)를 발생한다. 이하에서는 이들 내부 데이타 구조를 설명한다.
일반적인 제1도의 컴파일러의 설계, 특히 중간 언어 및 심볼 테이블의 설계는, VAX와 같은 “복합 명령 세트 컴퓨터”(CISC)로부터 PRISM, MIPS(32비트 RISC 머신)와 같은 “감소 명령 세트 컴퓨터”(RISC)까지 범위의 각종 아키텍쳐, 또는 진보된 64비트 RISCL 아키텍쳐를 어드레스하고자 하는 것이다. 이 설계는 타겟 머신(25)의 아키텍쳐가 어떤 기본 특징을 갖는다고 가정한다. 제1바이트 조직 및 어드레스 가능성이 가정되고 또한 2개의 상보적인 2진수 산술이 “리틀-엔디안(Little-endian)” 비트 오더링을 갖는 것으로 가정한다. “합리적인(Reasonable)” 어드레스 표시가 또한 가정되는데, 즉 어드레스는 레지스터에 조화된다.
일반적으로, 전단(20)은 프로그램의 중간 표시 생성시에 타겟 아키텍쳐(25)의 상세에 대해 망각할 수 있다. 중간 표시의 대부분의 구성은 타겟 아키텍쳐(25)와 무관한 잘 규정된 의미를 갖는다. 그러나, 전단(20)을 실시하는데 결정되어야만 하는 몇가지 이슈가 있다. 먼저, 하기 설명되는 바와 같이 모든 데이타 타입이 모든 아키텍쳐상에서 이용 가능한 것은 아니다. 둘째로, 산술 오버플로우 작용 및 “작은 정수” 산술의 표시는 이후 다시 설명되는 바와 같이 상이한 아키텍쳐상에서 변화될 수 있다. 세째로,(산술 시프트 연산자와 같은) 일부 연산자의 작용은 기초 머신 명령이 특정 아키텍쳐상에서 규정되는 피연산자 값의 하위 범위(Subrange)에 대해서만 규정된다. 이 지정된 범위외의 피연산자 값에 대해서, 상기 연산자는 어떤 특정한 머신에 대하여는 잘 적용할 수 있지만 다른 머신들상에서는 다른 작용을 가질 수 있다. 마지막으로, 규약(convention)의 호출은 다른 타켓 시스템(25)상에서 다르게되어, 어떤 경우에는 전단(20)이 동일 소스 언어구성에 대해 다른 중간 표시를 발생할 것을 요구한다.
용어“중간 언어”는 실행 가능 코드를 지정하기 위한 추상적인 언어를 말한다. “중간 언어 그래프”(ILG)(55)는 이 언어로 표현된 특정 프로그램이다.
그래프(55)의 중간 언어는 구문론적 구조를 제공하는 포인터를 갖는 메모리내 데이타 구조의 언어이다. 그러나, 교정 지원(debugging aid)으로서 컴파일러에 의해 기록된 IL 덤프(dump)용으로 사용된 ILG에 대한 대략 문자대로의 표시가 또한 있을 수 있다.
IL의 원천적인 개념은 제4도를 참조하여 상기 설명한 바와 같은 튜플이고, ILG(55)는 실행될 동작을 나타내는 튜플(35)로 만들어진다. 이 튜플(35)들은 여러가지 관계를 나타내는 포인터(예컨대, 피연산자 포인터 35)에 의해 함께 묶어진다. 가장 중요한 관계는 연산자-피연산자 관계(그 피연산자 각각에 대한 연산자로부터의 포인터(38)) 및 ILG의 각 기본 블럭내의 모든 튜플상의 선형 오더링(ordering)이며, 이것은 명목상의 실행 순서를 제공한다. 이 선형 순서는 블럭내의 튜플 수(40)에 의해, 그리고 루우틴 또는 모듈의 모든 블럭을 결합하는 포인터에 의해 표시된다.
ILG(55)에 의해 규정되는 계산은 다음과 같다.
(1) ILG의 BIGIN 튜플에서 시작함.
(2) 선형 오더내의 각 튜플을 평가하고, 그 피연산자의 세이브된 결과를 인출하며 그 결과를 계산 및 세이브하고, 및 그것에 대해 규정될 수 있는 어떤 이차적인 활동을 수행함.(“흐름 부울” 및 “조건부 선택” 연산자에 대한 이러한 간단한 평가에는 예외가 있다)
(3) 브랜치 튜플을 평가한 후에 그 브랜치 튜플에 의해 선택된 라벨 튜플에서 평가를 계속함.
이러한 규칙은 IL 그래프(55)의 “의미”를 규정한다는 것을 이해하여야 한다. 코드 발생기(29)는 하기의 규칙에 의해 지정된 바와 같이 그들의 종속성을 보존하는 한, ILG에서 의해 표시된 활동을 재배열하도록 허락된다.
(1) ILG(55)가 수식, 및 그 실행이 수식을 평가함으로써 계산된 값에 영향을 주는 설명문을 포함하면, 수식에 대해 발생된 코드 및 설명문에 대해 발생된 코드는 설명문 및 수식이 ILG에서 발생된 것과 동일한 순서로 실행되어야 한다.
(2) ILG(55)가 그 실행이 어떤 공통 수식을 평가함으로써 계산된 값에 영향을 주는 2개의 설명문을 포함한다면, 2개의 설명문에 대해 발생된 코드는 설명문들이 ILG에서 발생된 것과 동일한 순서로 실행되어야 한다.
설명문의 실행이 어떤 수식의 평가에 의해 계산된 값에 영향을 줄 때의 의문은 이후 설명되는 측면 효과 메카니즘을 참조하여 해결된다.
전단(20)에 의해 구성된 ILG(55)는 후단(12)에 의해 처리된 ILG와 동일하지 않다. 전단(20)는 콤팩트 IL 그래프를 발생하고, 후단(12)은 팽창된 IL 그래프를 처리한다. 후단(12)이 어떤 루우틴에 대한 코드를 발생할 때, 그것이 행하는 첫번째 일은 그 루우틴의 CILG를 EILG로 확장시키는 것이다. 두개의 모양 사이에는 몇가지 차이점이 있다. 첫째로, CIL은 EIL의 하위 레벨 튜플의 시퀀스로 팽창되는 “속기” 튜플을 제공한다. 둘째로, EIL 튜플을 나타내는 노드는 CIL 튜플을 타나태는 노드보다 훨씬 더 많은 필드를 갖는다. 추가적인 필드는 후단(12)에 의해 사용된 정보를 포함하지만, 이것은 CIL 노드의 필드로부터 IL 팽창기에 의해(또는 다른 후단 페이스에 의해) 계산될 수 있다. 세째로, CILG 및 EILG상에는 다른 구조상의 제한이 있다. 이 정보가 일반적으로 CIL과 EIL에 모두 관련된다 하더라도 이 기재는 콤팩트 IL에 관련된다.
심볼 테이블(30)의 구조는 컴파일되는 모듈(21)의 구조를 나타낸다. 테이블(30)의 중심(heart)이 블럭, 루우틴 및 모듈(21)의 어휘 범위를 나타내는 블럭 노드의 트리일 때, 트리 구조는 그들의 네스팅 관계(nesting relation)를나타낸다. 각각의 블럭 노드에는 그 블럭내에서 선언되는 심볼 노드의 리스트가 관련된다. 심볼 노드는, 변수, 라벨 또는 엔트리 포인트와 같은, 모듈에서의 심볼 존재(entity)를 나타낸다. 컴파일되는 모듈(21)의 일정한 값들은 문자 노드에 의해 표시된다. 문자 노드는 심볼 테이블(30) 및 ILG(55)로 부터 인용될 수 있다. 용어 문자 테이블은 또한 컴파일링에서 생성된 모든 문자 노드의 집합을 참조하기 위해 사용된다. 프레임 노드는 코드 및 데이타가 할당되는 기억 영역을 표시한다. 일반적으로 이들은 루우틴의 스택프레임이거나 PSECTs이다. 피라미터 노드는 피라미터 리스트를 만들기 위해 사용되는데, 이들은 엔트리 포인트 심볼(entry point symbol)과 관련된다. 각 파라미터 노드는 루우틴내의 피라미터 심볼을 엔트리 포인트의 인수 리스트내 위치와 관련시킨다.
[데이타 타입 :]
그래프(55)에서 사용된 중간 표시는 적은 세트의 타입만을 갖는 추상적인 머신(25)에 대한 프로그램을 설명하고, 그 데이타 타입은 하기 리스트에서 설명된다. 이 데이타 타입들은 전단(20)에만 관련되는 모듈(21)의 소스 언어의 데이타 타입과 구별된다. 각각의 타겟 머신(25)에 대하여 각각의 소스 언어 데이타 타입을 나타내는데 사용되는 데이타 타입을 결정하는 것은 전단(20)이 해야 할 일이다.
데이타 타입
널(Null)
표시(Representational)
스칼라
어드레스
부호 정수(Signed Integer)
무부호 정수(Unsigned Integer)
부동 소수점
복소수(complex)
부울(Boolean)
널 데이타 타입은 값을 계산하지 않은 튜플의 타입인 특수한 데이타 타입이다. 표시 데이타 타입은 그 값이 타겟 머신 아키텍쳐에서 특정 표시를 갖고 있는 타입이다. 표시 데이타 타입은 스칼라 데이타 타입과 군(aggregate) 데이타 타입으로 나뉜다. 스칼라 데이타 타입은 그 값들이 메모리 위치 또는 레지스터의 작은 고정수로 표시될 수 있는 타입이다. 상기 스칼라 데이타 타입은 어드레스 데이타 타입 및 산술 데이타 타입으로 세분된다. 산술 타입은 적당한 수의 비트에 적합할 수 있는 것과는 다른 종류의 데이타를 나타내기 위해 사용될 수 있음을 명심하라. 특히 소스 언어 문자 및 논리 데이타 타입은 정수 데이타 타입으로 나타내어져야 한다. 여기에는 단일 어드레스 데이타 타입(ADDR)이 있다. 타입 ADDR의 값은 32 또는 64비트를 갖는 2진수 정수로서 표시된다.
부호 정수 데이타 타입 INT8, INT16, INT32 및 INT64가 있는데, 여기에서 INTx-1타입의 값은x-1비트를 갖는 부호 있는 2진수 정수로서 표시되고 따라서 (2x-1)…(2x-1-1)의 범위에 있다. 타입 INT8은 또한 IBYTE로서 인용될 수 있다. 타입 INT16은 또한 IWORD로서 인용될 수 있다. 타입 INT32는 또한 ILONG로서 인용될 수 있다. 타입 INT64는 또한 IQUAD로서 인용될 수 있다. 어드레스와 동일한 수의 비트를 갖는 정수 타입은 또한 IADDR로서 인용될 수 있다. 타켓 아키텍쳐에 대해 지지되는 가장 큰 부호 정수 타입(INT32 또는 INT64)은 또한 IMAX로서 인용될 수 있다. 어떤 2진수 스케일링(scaling)(PL/I에서와 같이)도 전단에 의해 제공되어야 하며, 스케일링된 2진수 데이타 타입에 대한 IL 규정은 없다.
무부호 정수 데이타 타입 UINT8, UINT16, UINT32 및 UINT64가 있는데, 여기에서 타입 UINTx-1의 값은x-1비트를 갖는 부호 있는 2진수 정수로서 표시되고, 따라서 0…(2x-1)의 범위에 있다. 타입 UINT8은 또한 UBYTE 또는 CHAR8로서 인용될 수 있다. 타입 UINT16은 또한 UWORD 또는 CHAR16으로서 인용될 수 있다. 타입 UINT32 또한 ULONG로서 인용될 수 있다. 타입 UINT64 또한 UQUAD로서 인용될 수 있다. 어드레스와 동일한 수의 비트를 갖는 무부호 정수 타입은 또한 UADDR로서 인용될 수 있다. 타겟 아키텍쳐에 대해 지지되는 가장 큰 무부호 정수 타입(UINT32 또는 UINT64)은 또한 UMAX로서 인용될 수 있다.
부동 소수점 데이타 타입으로는 VAX 부동 소수점 타입인 REALF, REALD, REALG 및 REALH와, IEEE 부동 소수점 타입인 REALS, REALT, REALQ 및 REALE가 있다. 이들 모두가 어떤 특정 타겟 아키텍쳐상에서 반드시 지지되는 것은 아니다.
복소수 데이타 타입으로는 CMPLXF, CMPLXD, CMPLXG, CMPLXS 및 CMPLXT가 있다. 복소수 값은 대응하는 실수 타입의 한쌍의 값으로써 표시되며, 이것은 복소수 값의 실수부와 허수부를 표시한다. 지지된 부동 소수점 타입 형태에 대응하는 복소수 타입만이 특정 타겟 아키텍쳐상에서 지지된다.
군 데이타 타입의 값은 일련의 근접 요소들로 구성된다. 군 값은 그 보디(body), 요소들의 실제 순서, 길이 및 그 시퀀스내의 요소수에 특징이 있다.
군 타입으로는
(a) 타입 CHAR8의 요소들을 갖는 문자 스트링, 타입 STR8.
(b) 타입 CHAR16의 요소들을 갖는 연장된 문자 스트링, 타입 STR16.
(c) 요소들이 가능한한 단단하게 묶여진 단일 비트들인 비트 스트링, 타입 BITS.
(d) 요소들이(유도 부호 디지트를 갖는, 바이트마다 2개씩 묶여진 4비트 BCD 디지트로서 표시된) 10진수 디지트인 PL/I 및 COBOL 10진수 스트링, 타입 DECIMAL. CECIMAL 값은 그 정확성(유도 부호 디지트를 계수하지 않고), 그것이 포함하는 디지트의 수, 및 그 규모, 즉 소수점 후에 오는 것으로 간주되는 디지트의 수에 특징이 있다.
군 값의 요소들은 제로에서 시작하여 번호가 부여된다.(이것은 소스 프로그램 스트링 인덱스를 IL 스트링 인덱스로 번역할 때 많은 전단들이 1을 감산함을 주의한다.)
스트링 동작에서 처리될 수 있는 요소의 수에는 제한이 없다. 플래그는 길이가 65535 문자를, 초과하지 않도록 보장되는 문자 스트링 표시를 전단이 나타내도록 차후에 도입된다. 따라서 상기 표시는 VAX 문자 스트링 명령으로 충분히 계산될 수 있다. 메모리에서 가변 길이 스트링의 길이 워드는 아직은 단지 16비트일 것이다. 10진수 스트링은 모든 타겟 아키텍쳐상에서 31 디지트(더하기 부호 비트)로 제한된다.
각종 타겟 아키텍쳐에 대한 대표적인 타입 시스템의 상세의 일예는 표 6에 나타내었다.
단일 부울 데이타 타입(BOOL)이 있다. 이것은 프로그램의 실행중에 계산된 논리 값의 타입이다. 이것은 특정된 물리적 표시를 갖지 않는다. 예를 들어, 부울 값은 2진수 정수의 값, 프로세서 조건 코드의 값 또는 프로세서 프로그램 카운터의 값에 표시될 수 있다. 특히, 타입 BOOL은 소스 언어로 나타날 수 있는 어떤 논리 또는 부울 데이타 타입들에도 대응하지 않는다. 이들은 INT 또는 UINT 값으로서 표시되어야 하고, 필요에 따라 타입 BOOL로 또는 타입 BOOL로부터 변환되어야 한다.
이제, 중간 언어내의 모든 튜플에 공통인 일반적인 특징 및(중간 언어의 루우틴인) ILG(55)의 구조상의 특징에 대하여 설명한다.
ILG(55)는 IL 튜플 노드(일반적인 단지 튜플이라고 함)로 구성된다. 모든 튜플들은 표 7에 목록된 필드를 포함한다. 속성이라고 하는 다른 필드들은 특정 종류의 튜플에서만 발생한다.
전단(20)에 의한 사용을 위해 예비된 임의 크기의 스페이스로 할당될 수 있는 심볼 테이블 노드와는 달리, CIL 튜플 노드는 여기에서 특정된 필드만을 포함한다. EIL 튜플 노드는 후단(12)에 전용인, 튜플 노드 어드레스로부터의 네가티브 오프셋(negative offset)에 위치된, 추가 필드를 포함한다.
[ILG의 구조]
ILG내의 하나의 튜플은 2가지의 다른 방법, 즉 피연산자로서 또는 속성으로서 다른 튜플을 인용할 수 있다. 연산자-피연산자 관계만을 생각할 때, CILG는 지향된 아시클릭 그래프(directed acyclic graph : DAG)이고 EILG는 숲(즉, 트리의 집합)이다.
속성 포인터(39)는 ILG상에 추가 구조를 생성하고 또한 ILG로부터 심볼 테이블(30)로의 참조를 허용한다. 가장 중요한 구조상의 관계는 다음 튜플 및 이전 튜플 속성 포인터에 의해 규정된 ILG의 선형 순서이다. CILG내의 모든 튜플들은 선형 순서에 의해 규정된 단일 리스트에서 발생한다. EILG의 튜플은 각 기본 블럭마다 하나씩 원형 리스트의 집합에서 발생한다.
하기의 규칙은 ILG의 구조에 적용된다. 전단(20)이 상기 규칙을 위반하는 CILG를 생성하면, 비록 후단이 편리한 곳에서 그 위반들을 검출하고 컴파일링을 종료하고자 하더라도 그 결과는 예측 불능이다.
(a) 결과 타입이 NULL인 튜플은 설명문 튜플로서 인용되고, 결과 형태가 NULL이 아닌 튜플은 수식 튜플로서 인용된다.
(b) CIL에서 :
(i) 스칼라 또는 부울 수식 튜플은 하나 이상의 다른 튜플의 피연산자일 수 있다. 군식 튜플은 정확히 하나의 다른 튜플의 피연산자로서 사용되어야 하고 동일한 기본 블럭에 있어야 한다(하기 참조).
(ii) 피연산자는 수식 튜플, 심볼 노드 또는 문자 노드일 수 있다.
(iii) 피연산자로서 사용된 심볼 노드는 항상 타입 ADDR을 갖는다. 피연산자로서 사용된 문자 노드는 문자의 데이타 타입을 갖는다.
(iv) 레지스터에 할당된 변수를 나타내는 심볼은 통상의 의미에서는 어드레스를 갖지 않는다. 그러나, 그러한 심볼은 메모리로부터 판독하거나 메모리에 기록하는(FETCH 또는 STORE) 튜플의 어드레스 피연산자로서 사용될 수 있고, 이 경우에 튜플은 지시된 레지스터를 액세스 한다.
(v) 심볼이 스택 프레임의 변수를 나타내면, 그 스택 프레임은 현재의 루우틴 또는 심볼 테이블 블럭 트리의 전신(ancestor)들중 하나와 연합되어야 하며, 그렇지 않으며 실행시에 스택 프레임을 찾아낼 방법이 없다.
(c) EIL에서 피연산자는 수식 튜플이어야 하고, 각각의 수식 튜플은 정확히 하나의 다른 튜플의 피연산자이어야 한다.
(d) 설명문 튜플은 어떤 다른 튜플의 피연산자도 아닐 수 있다.
(e) 다른 튜플의 피연산자인 튜플은 ILG의 선형 오더링에서 그 튜플을 진행시켜야 한다.(EILG에서 이것은 피연산자 및 연산자가 동일한 기본블럭에서 발생하여야 한다는 것을 의미한다.)
(f) 수식 튜플은 그것이 피연산자인 각각의 튜플을 지배하여야 한다. 즉, 도중에 그 튜플의 각 피연산자와 마주침이 없이 루우틴의 엔트리 지점으로부터 튜플로 가져가는 것은 불가능하다.
이 섹션에서의 다음 단락은 주간 언어에서 이용할 수 있는 동작의 종류 및 그 동작을 나타내는데 사용되는 연산자를 설명한다. 개개의 연산자는 모두 <REFERENCE)>(파트_튜플_딕셔너리(dictionary)), 튜플딕셔너리라고 부르는 데이타 구조내에 수집된다. 딕셔너리내의 각 연산자는 구조화된 포맷을 사용하여 기록된다. 표 8은 이 포맷의 메인 케테고리, 각각의 아래에 나타나는 정보, 및 정보를 나타내는데 사용된 포맷을 나타낸다.
튜플의 포맷 섹션은 피연산자의 수를 지정하고 그리고 허락된 연산자, 피연산자 및 단일 라인의 타입으로 결과 타입을 지정한다.
op 타입(타입 1,…타입 n) : 결과
여기에서 op는 튜플 연산자의 이름이고, 타입은 허용 가능한 연산자 타입을 나타낸다. “타입”이 생략되어 있으면 연산자 타입은 NULL이어야 한다. 그렇지 않으면, 타입은 하기의 것중 하나이어야 한다.
(a) 특정 타입명(ADDR,BOOL,BITS,IADDR, 등)은 특정 타입만이 허락됨을 나타낸다.
(b) INT, UINT, REAL, CMPLX 또는 STR은 특정군에 속한 어떤 타입도 적법함을 나타낸다. 예를 들어 CMPLX는 CMPLXF, CMPLXD, CMPLXG, CMPLXS 및 CMPLXT가 모두 허락됨을 의미하고, STR은 STR8 및 STR16이 허락됨을 의미한다.
(c) ALL은 NULL 이외의 어떤 타입도 적법함을 나타낸다.
(d) 다음과 같이 문자 I, U, R, C, A, S 및 B의 스트링은 그 문자들중 하나에 의해 표시된 군에 속하는 어떤 타입도 허락됨을 나타낸다.
I INT A ADDR
U UINT S STR
R REAL B BITS
C CMPLX
수식 “타입 1,…, 타입 n”는 튜플의 피연산자의 허용 가능한 타입을 나타낸다. 괄호내의 리스트가 생략되어 있으면, 연산자는 피연산자를 취하지 않는다. 그렇지 않다면 튜플은 리스트내의 각 타입에 대하여 하나의 피연산자를 가져야 한다. 각 타입 i는 하기의 것중 하나이어야 한다.
(a) T는 피연산자 타입이 연산자 타입과 같은 것이어야 함을 의미한다.
(b) 특정 타입 명(ADDR,BOOL,BITS,IADDR, 등)은 피연산자가 특정 타입을 가져야 함을 의미한다.
(c) 타입 코드 문자 I, U, R, C, A, S 및 B의 스트링은 타입 지정자에 대해서 갖는 것과 동일한 의미를 갖는다. “어떤 정수”를 의미하는 타입 지정자 IU를 갖는 피연산자는 일반적으로 발생 코드에서 타입 IMAX로 변환됨을 주의한다. 따라서 프로그램 작용은 그러한 피연산자의 실제값이 타입 IMAX로 변환될 수 없는 경우에는 규정되지 않는다.
(d) 연산자 및 피연산자 타입 지정자가 REAL과 CMPLX 또는 STR과 CHAR이면, 실제 연산자 및 피연산자 타입은 일치되어야 한다. 예를 들어, 타입 지정“CADD.CMPLX(T,REAL) : T”는 연산자 타입이 CMPLX인 경우 제2피연산자가 타입 REALF를 가져야 하고 연산자 타입이 CMPLXT인 경우 제2피연산자가 타입 REALS를 가져야 한다는 것을 나타낸다. 연산자 타입이 SB, 즉, 문자 스트링 또는 비트 스트링이고 피연산자 타입 지정자가 CHAR이면, 피연산자 타입은 연산자 타입이 STR8인 경우 CHAR8이어야 하고 연산자 타입이 STR16인 경우 CHAR16이어야 하며, 연산자 타입이 BITS인 경우 IMAX이어야 한다. 즉, IMAX는 스트링 타입 BITS에 대응하는 문자 타입으로써 처리된다.
튜플의 실제 피연산자는 결과 타입이 피연산자 타입 리스트에 의해 지정된 타입과 일치하는 튜플 노드이어야 한다. CIL에서, 피연산자들은 항상 타입 ADDR을 갖는 것처럼 처리되는 심볼 노드이거나, 그들의 데이타 타입 필드에 의해 지정된 타입을 갖는 것처럼 처리되는 문자 노드일 수있다.
수식 “Result”는 허용 가능한 결과 타입을 지정한다. 만일 이것이 생략되어 있으면, 연산자는 설명문 연산자이고 튜플의 결과 타입은 NULL이어야 한다. 그렇지 않다면 연산자는 피연산자 타입 지정자와 정확히 같은 방법으로 해석된다.
어드레스 수식은 중간 언어에서의 인용문들중 하나이다. 어드레스 수식의 가장 간단한 형태는 심볼이다. 즉, 튜플 노드의 피연산자 필드는 그 심볼과 관련된 메모리 어드레스(또는 레지스터)를 나타내도록 심볼 노드의 어드레스를 포함할 수 있다. 어드레스 값은 또한 메모리(“포인터 변수”)로부터 그 어드레스 값을 인출함으로써, 또는 산술 값을 캐스팅(casting)함으로써, 또는 선중분 튜플, 후중분 튜플, 또는 하기 리스트의 튜플들중 하나를 평가함으로써 얻어질 수 있다.
데이타 액세스 튜플은 값이 메모리로부터 로드되거나 메모리에 기억되게 하는 튜플이다. (여기에서 단어 “메모리”는 타겟 CPU25의 레지스터 세트내의 레지스터를 포함한다. CPU25의 레지스터와 정상 메모리 위치 사이의 유일한 차이는 레지스터의 “어드레스”가 단지 데이타 액세스 튜플에서 사용될 수 있다는 점이다.) 데이타 액세스 연산자는 표 9에 리스트된다.
각각의 데이타 액세스 튜플에서, 제1 피연산자는 어드레스 수식이다. 각각의 데이타 액세스 튜플은 또한 긴 단어 정수를 포함하는 오프셋 속성을 갖는다.
액세스되는 메모리 위치의 어드레스는 구동 시간 어드레스 피연산자와 컴파일-시상수 오프셋 속성의 합이다.
모든 데이타 액세스 튜플은 표 10에 리스트된 일부 또는 모든 속성을 가질 것이다. 효과, 효과2, 및 기본 심볼 속성의 사용은 이후 “효과 표시를 위한 인터페이스” 섹션에서 보다 상세히 설명된다.
또 다른 타입의 인용문은 어레이 인용문이다. APLUS 및 AMINUS 튜플은 모든 어드레스 계산을 위해 충분하다. 그러나, 이들은 어드레스 계산의 의미를 대하여 어떠한 정보도 제공하지 않는다. 특히, 이들은 소스 코드에 나타났을수도 있는 어레이 인용문 및 첨자 수식에 대하여 어떠한 정보도 제공하지 않는다. 이 정보는 벡터화를 위해 필요하다. 그러므로, IL은 특히 어레이 인용문을 묘사하는 튜플을 갖는다.
예를 들어, 로컬 X : 벡터[20,롱(long)]으로서 선언되는 BLISS 벡터가 주어지면 .X[.I]에 대한 인용문은 하기와 같이 표시될 수 있다.
$1 : FETCH. INT32(I) ;
$2 : SUBSCR. IADDR($1,[4],[0] ; POSITION=1) ;
$3 : FETCH. INT32(X,$2) ;
Var Y : 0.225의 팩(packed) 어레이[1…10,1…10]로서 선언된 파스칼 어레이가 주어지면, 지정문 Y[I,J] : =Z는 하기와 같이 표시될 수 있다.
$1 : FETCH. INT32(J) ;
$2 : SUBSCR. IADDR($1,[1],[0] ; POSITION=1) ;
$3 : FETCH. INT32(I) ;
$4 : SUBSCR, IADDR($3,[10],$2 ; POSITION=2) ;
$5 : FETCH. UINT8(Z) ;
$6 : STORE. UINT8($4-11,$5) ;
기본 어레이 인용문 연산자는 AREF와 SUBSCR이다. AREF는 어레이내의 특정된 요소의 어드레스를 생성한다. SUBSCR은 어레이 요소의 오프셋을 계산한다.
제1 피연산자 또는 AREF 튜플은 어레이의 기본 어드레스를 나타내는 어드레스 수식이다. 제2연산자는 기본 어드레스로부터 어레이의 요소까지의 바이트 오프셋을 계산하는 SUBSCR 튜플이다. AREF 튜플은 SUBSCR 튜플의 값을 기본 어드레스에 가산하여 색인된 요소의 어드레스를 계산한다. 사실, AREF(원점,첨자)의 코드는 APLUS(원점,점차)의 코드와 동일하다.
SUBSCR 튜플은 어레이내의 하나의 차원을 따른 요소의 오프셋을 계산한다. 그 피연산자는,
(a) 요소 색인. 첨자 수식의 개개의 인덱스들은 제로 원점을 위하여 표준화되지 않는다. 그대신 어레이선언의 비제로(non-zero) 하부 바운드를 설명하기 위한 원점 오프셋은 AREF 튜플의 어드레스 피연산자 또는 요소 어드레스를 사용하는 튜플의 오프셋 필드에 가산되어야 한다.
(b) 스트라이드(stride). 이것은 차원을 따르는 연속적인 요소의 어드레스간의 차이이다. 긴 워드의 간단한 벡터에 대해서, 스트라이드는 문자 4로 되겠지만, 다차원 어레이에 대해서는 어레이의 고차원열(또는 더큰 단면)의 “요소”가 된다.
(c) 첨자 수식의 나머지(즉, 첨자 수식의 나머지 인덱스)에 대한 수식. 이것은 다른 SUBSCR 수식 또는 정수 상수 제로를 표시하는 문자 노드이어야 한다.
SUBSCR(인덱스,스트라이드,나머지)에 대한 코드는 ADD(MUL(인덱스,스트라이드),나머지)에 대한 코드와 동일하다.
SUBSCR 튜플은 또한 위치 속성을 가지며, 이것은 어레이 인용문의 첨자 리스트내에서 인덱스의 위치를 나타낸다. 위치 번호는 주어진 어레이에 대한 모든 인용문에서 동일한 첨자 위치를 식별한다. 가장 효율적인 벡터화에 있어서, 위치 1은 가장 빠르게 변하는 첨자이어야 하고 위치 2는 그 다음으로 가장 빠르게 변화하는 첨자이어야 한다.
어떤 다른 섹션에 정말로 적합하지 않는 수개의 튜플 연산자가 있다. 이들 잡다한 연산자들은 다음과 같다.
[산술 튜플 ]
산술 튜플은 “산술” 값, 즉 정수, 실수, 복소수를 관리하기 위해 사용된다. 이것은 가산 및 승산과 같은 통상적인 산술 동작 뿐만 아니라 인출, 기억 및 변환을 포함한다.
VAX와 RISC 아키텍쳐의 시프트 명령은 서로 다르기 때문에 완전한 추상적 IL 시프트 연산자는 하나 또는 2개의 아키텍쳐 상에서 비효율적인 코드를 확실하게 발생하도록 될 것이다. 반면에 IL은 많은 소스 언어가 몇 종류의 시프트 연산자를 갖기 때문에 시프트를 지지하여야 한다. 절충안으로서 IL은 하기의 연산자를 제공한다(시프트 연산자는 어느 것도 산술 오버플로우 예외를 일으키지 않는다).
(a) SHL, SHR 및 SHRA는 각각 좌측 시프트, 논리 우측 시프트 및 산술 우측 시프트를 행하고 포티지브 시프트 카운트를 요구한다.(즉, 그 작용은 시프트 카운트가 네가티브인 경우에는 규정되지 않는다.) 이들은 C 시프트 연산자를 지지하고 RISC 아키텍쳐 시프트 명령에 직접 맵한다.
(b) SH는 그 피연산자가 포지티브이면 좌측 시프트를 행하고, 그 피연산자가 네가티브이면 우측 시프트를 행한다. 이것은, BUJSS 시프트 연산자를 지지하고, VAX 시프트 명령에 직접 맵한다.
(c) ROT는 회전 연산자이다. 비록 VAX와 RISC 아키텍쳐에서는 이것을 다르게 묘사하였지만, 모든 경우에서의 실제 작용은 카운트가 카운트 피연산자의 최하위 n비트에 의해 지정되는 좌회전으로써 특정지어 질 수 있다. 여기에서 n은 레지스터 사이즈의 베이스 2 알고리즘이다(예를 들어 VAX와 MIPS상에서 회전 카운트는 카운트 피연산자의 최하위 5비트이다).
정수 오버플로우는 또 다른 특징으로 고려된다. 모든 타겟 머신에서 소스 언어의 의미론을 만족시키며 그 의미론에 의해 부과된 구속을 받는데 가능한한 효율적으로 되는 코드가 발생되도록, IL의 정수 산술에 대한 크기를 특정하게 하는데는 문제가 있다. 특히(VAX와 같은), 일부 머신들은 바이트와 워드 산술을 양호하게 행하지만, 반면에 RISC 머신은 전형적으로 단지 긴 워드 산술만을 행한다. 모든 크기 변환을 행하는 것은 VAX상에서는 소비성일 뿐이지만, 진정한(ture) 바이트 또는 워드를 에뮬레이트하는 것은 RISC 머신상에서 비효율적이다.
하기 규칙들은 충분한 가요성을 갖는 코드 발생기가 모든 타겟 머신에 대하여 합리적인 코드를 발생하게 하기 위한 것이다(하기 INT 타입에 대해 말하여진 모든 것은 UINT 타입에 동일하게 적용된다).
(a) 수식의 결과 타입이 INTx-1이면, 컴파일러는 y비트 산술로 지시된 계산을 수행한다(여기에서 yx). 이것은, 원래의 x비트 계산이 오버플로우되는 경우, x 이상의 주요 비트를 갖는 y비트 결과를 발생시킬 수도 있다. 예를 들면 ADD.INT16는 32비트 가산으로 실시될 수 있다. 20000+30000은 16비트 가산으로 수행될때는 오버플로우를 일으키지만, 32비트 가산으로서 수행될때는 적법한 32비트 수 50000을 발생한다.
(b) 각각의 산술 연산자는 억제 오버플로우 플래그(이것은 튜플 결과 타입이 INT 또는 UINT일때에만 의미를 갖는다)를 갖는다. 이 플래그가 세트되면, 튜플에 대해 발생된 코드는 계산 결과에 관계없이 어떤 종류의 오버플로우 조건도 보고하지 않아야 하며(그 결과가 XCVT 튜플의 피연산자로서 사용될 때를 제외하고), 그 결과에서 있을 수 있는 무관한 고차 비트의 존재를 무시할 수 있다. 억제 오버플로우 플래그는 오버플로우가 어떤 방법으로도 발생할 수 없는(LAND와 같은) 튜플에서 정의됨을 유의한다. 이들 튜플에 대한 오버플로우의 억제는 특히 용이하다. 억제 오버플로우 플래그는 동작이 오버플로우하는 것이 어의적으로 틀린 상황에 대해 의도된다. 이것은 어떤 아키텍쳐상에서 비용이 더 많이 드는 코드를 야기할 수 있다.
예를 들면, VAX상에서 여분의 코드가 오버플로우 검출을 억제하기 위해 요구된다. 따라서 동작이 오버플로우하는지 여부가 별로 중요치 않은 경우, 또는 특정 동작이 결코 오버플로우할 수 없음을 전단이 인식하는 경우, 이 플래그는 컴파일러가 가장 효율적인 코드를 발생하도록 클리어되어야 한다.
(c) 루우틴 블럭 노드는 검출 오버플로우 플래그를 갖는다. 이 플래그가 클리어되면, 후단은 정수 산술 동작에서 오버플로우를 검출하기 위하여 코드를 발생할 필요가 없다. 그러나 이것이 보다 효율적이면, 즉 오버플로우 검출의 강제적인 억제가 특정 튜플에 억제 오버플로우 플래그를 세팅함으로써만 달성될 수 있는 경우에는, 오버플로우를 검출하는 코드를 발생하는 것은 자유이다.
(d) 검출 오버플로우 플래그가 루우틴 블럭 노드에서 세트되면, 발생된 코드는, 각각의 수식 트리에 대하여, 그 수식에 대해 계산된 결과가 유효하거나 정수 오버플로우 예외가 표시되는 것을 보장하여야 한다. 이것은 오버플로우가 수식의 모든 가능한 부수식(Subexpression)에서 검출되는 필요 조건이 아니다. 예를 들어서, A, B, C 및 X가 16비트 변수로서 A는 32767이고 B와 C는 1이라고 가정한다. 지정문 X : A+B-C에서, 발생된 코드는 32비트 산술을 사용하여 A+B-C를 계산하고, 그 다음에, 그 결과가 16비트 결과인지를 그것을 기억하기 이전에 체크한다. 이것은, 16비트 산술로 계산된 경우 동일한 수식이 정수 오버플로우 에러를 발생한다 하더라도, 정확한 답 32767을 기억한다. 반면에, 지정문 X : =A+B는 값 32768을 정확히 계산하지만 그 다음에 그것을 X에 기억시키려고 할때 오버플로우 예외를 발생한다. 오버플로우가 검출되어야 하는 장소의 집합은 명확하진 않지만, 우측의 기억 및 루우틴 호출에서의 인수를 반드시 포함한다.
(e) 피연산자의 값을 복귀시키고 그 표시의 어떤 무관한 고차 비트들도 실제 피연산자의 부호와 일치하도록 하는 XCVT 변환 연산자를 또한 주목하라. 예를 들어, E가 32비트 산술을 사용하여 평가된 UINT8 수식이라면, XCVT, UINT8(E : INT16)은 상위 8비트가 제로로 되는 것이 확실한 16비트 정수일 것이다. 일반적으로 E가 타입 T의 수식이면, XCVT.T(E : T)는 값의 표시가 그것의 공칭 크기와 일치되게 하는데 사용될 수 있다.
(f) 어떤 수식에서 정수 피연산자의 표시가 피연산자의 공칭 크기를 초과하는 상위 비트를 포함하면, 발생된 코드는 완전히 표시된 값 또는 공칭 크기에서의 값을 사용하는 것이 자유로워진다. 이것이 허용 불능일때, 전단은 그 표시로부터 원치않는 고위 비트를 버리도록 XCVT 튜플을 발생하여야 한다.
부동 소수점 오버플로우 예외의 검출을 무력화시키는 어떠한 메카니즘도 IL에는 없다. 부동 소수점 오버플로우는 항상 예외 표시를 발생한다. 부동 소수점 언더플로우의 표시는 루우틴 레벨에서만 제어된다. 루우틴 블럭 노드는 검출 언더플로우 플래그를 갖는다. 이것이 세트되면, 컴파일러는 그 루우틴에서 발생하는 어떤 부동 소수점 언더플로우도 검출 및 보고하는 코드를 발생할 것이 요구된다. 그렇지 않으면, 발생된 코드는 부동 소수점 언더플로우를 무시하여야 한다.
변환 연산자는 다른 산술 타입의 값에 관련되는 하나의 산술 타입의 값을 계산할 것이다. 실수-정수 변환을 위한 ROUND 및 TRUNC 연산자, 실수-복소수 변환을 위한 CMPLX 연산자 및 복소수-실수 변환을 위한 REAL 및 IMAGV 연산자는 모두 유사하다(ROUND와 TRUNC는 또한 실수 결과 타입으로 규정된다).
CVT는 범용의 변환 연산자이다. 이것은 어떤 두개의 산술 타입 사이에서도 변환을 행한다. 직접 행하여지는 유일한 변환이 UINT-INT, INT-REAL, 및 REAL-CMPLX(및 물론 INT16-INT32와 같은 타입내의 변환)이라는 것을 인식하는 것은 중요하다. 이것은, 예를 들면, CMPLXG-UINT16 변환이 실제로 일련의 변환 CMPLXG-REALG, REALG-INT32, INT32-UINT16으로서 수행된다는 것을 의미한다. 이것은 VAX의 파스칼의 작용이 아니며, VAX 파스칼은 직접적인 실수-무부호 변환을 행한다.
XCVT는 정수 타입으로서만 처리되는 특수 연산자이다. CVT와 같이, 이것은 그것의 피연산자와 산술적으로 동일한 결과 타입의 값을 산출한다. 그러나, 이것은 피연산자 표시가 그 값과 산술적으로 동일하도록 피연산자 표시의 상위 비트를 첫번째로 변환시키는 특징을 갖는다.
예를 들어 하기의 식을 생각한다.
XCVT(ADD.UINT8([UINT8=255],[UINT8=2]) : INT16).
수식이 32비트 산술로 계산되면, ADD의 결과는 레지스터가 %X00000101(2 57)를 포함하게 된다. XCVT는 그 다음에 이미 유효 16비트 부호 정수로 되어 있는 %X00000001(1)를 남긴채 상위 비트를 제거한다.
CAST는 값이 아닌 비트 패턴을 다루기 때문에 실제로는 변환 연산자가 아니다. CAST 튜플은 그 피연산자와 동일한 비트 패턴을 갖는 그 결과 타입의 값을 산출한다(만일 필요하다면 제로 비트를 잘라 줄이거나 연결시킨다).
또 다른 타입은 변수 수정 연산자이다. OPMOD(여기에서 OP는 ADD,LAND 등임)로부터의 명칭을 갖는 연산자들은 모두 어드레스 피연산자 및 값 피연산자를 갖는다. 이들은 지정된 어드레스로부터 산술 값을 인출하고, 그것과 값 피연산자 사이에서 지시된 동작을 수행하며, 동일 어드레스에 결과적인 후단(back)을 기억한다. 이들은 또한 계산된 값을 산출하며, C ; s op=연산자를 실시하도록 의도된다. 예를 들어서, 코드시퀀스
$1 : ADDMOD.REALF(X,[%F0.1]) ;
$2 : STORE.REALF(Y,$1) ;
는 다음과 동일한 효과를 가질 것이다.
$1 : FETCH.REALF(X) ;
$2 : ADD.REALF($1,[%F0.1]) ;
$3 : STORE.REALF(X,$2) ;
$4 : STORE.REALF(Y,$2) ;
이 연산자들은 또한 OPMODA 및 OPMODX 형태를 가지며, 묶여진 어레이 요소 또는 비트 필드내의 값을 인출, 갱신 및 교체한다.
PREINCR.PREINCRA 및 PREINCRX 연산자는, 값 피연산자 대신 이들의 컴파일 시상수 증분값을 포함하는 속성 필드를 갖는다는 것을 제외하면, ADDMOD, ADDMODA 및 ADDMODX와 본질적으로 동일하다. 이들은 산술 변수 뿐만 아니라 어드레스(포인터 변수)에도 적용될 수 있다. 이들은 C의 선증분 및 선감분 연산자를 실시하도록 의도된다.
POSTINCR, POSTINCRA 및 POSTINCRX 연산자는, 튜플의 값이 메모리 위치에 다시 기억되어졌던 값이라기 보다는 그 갱신전에 메모리 위치가 유지하고 있는 값이라는 것을 제외하면, PREINCR 및 PREINCRX 튜플과 동일하다. 이들은 C의 후증분 및 후감분 연산자를 실시하도록 의도된다.
[스트링]
컴파일러의 스트링(또는 군) 타입은 그 값들이 기본 타입으로부터의 일련의 값들인 타입이다. 이 타입들은 다음과 같다.
STR8, 일련의 8비트 문자들(타입 CHAR8).
STR16, 일련의 16비트 문자들(타입 CHAR16).
BITS, 일련의 단일 비트들.
DECIMAL, 일련의 십진수 디지트들 및 관련 정밀도.
일련의 문자 또는 비트 스트링의 요소들은 0에서부터 n-1까지 번호가 부여되어 있으며, 여기에서 n은 스트링 길이를 나타낸다. 8비트 문자 스트링이 어드레스 A에서 메모리에 표시되면, 어드레스 A에서의 바이트는 그 스트링의 첫번째 문자를 포함하고 어드레스 A+1에서의 바이트는 그 스트링의 두번째 문자를 포함하며, 이와 같이 하여 어드레스 A+n-1에서의 바이트는 그 스트링의 최종문자를 포함하게 된다. 16비트 문자 스트링이 어드레스 A에서 메모리에 표시되면, 어드레스 A에서의 워드는 그 스트링의 첫번째 문자를 포함하고, 어드레스 A+2에서의 워드는 그 스트링의 두번째 문자를 포함하며, 이와 같이하여 어드레스 A+2(n-1)에서의 워드는 그 스트링의 최종문자를 포함한다. 비트 스트링이 어드레스 A에서 메모리에 표시되면, 그 스트링의 첫번째 8비트는 어드레스 A+1에서 그 바이트의 최하위 비트에서 최상위 비트까지 된다.
군 값들은 일반적으로, 레지스터에서 발생할 수 있는 스칼라 값과는 달리, 또는 머신 명령에서의 문자 피연산자와 같이 메모리의 어디에서든지 표시되어야 한다. 그러나 중간 언어의 의미론적 모델은 스트링이 스칼라와 같이 인출되고, 관리되며 기억될 수 있다는 것이다. 컴파일러는 중간 스트링의 값을 유지하도록 템포러리(temporary)를 할당하는 임무를 갖는다.
스트링 동작을 위해 발생된 코드는 피연산자들간에 오버랩이 있을 때에도 이 모델과 일치하여야 한다. 예를 들어서, IL 설명문 STOREF.STR8(A+1,[20],FET CHF.STR8(A,[20])은 20문자 스트링을 메모리의 한위치위로 이동시킨다. A에서 문자의 20개 카피를 만드는 것은 간단하지 않다.
스트링은 그 길이가 제로이면 비어있다고 말하여 진다. 머리는 비어 있지 않은 스트링의 첫번째 요소를 복귀시키는 기능이 있고 꼬리는 비어있지 않은 스트링의 첫번째를 제외한 모든 요소들을 포함하는 스트링을 복귀시키는 기능이 있으며, 공백은 스트링이 비어 있으면 참이고 그렇지 않으면 거짓인 기능이 있는 것으로한다. 이때 두개의 스트링 X와 Y간의 관계는 표준 비교 연산자(EQL,NEQ,LSS,LEQ,GTR,GEQ)에 의해 테스트될 때 다음과 같이 정의된다.
empty(X)∧empty(Y)이면 X=Y,
empty(X)∨-empty(Y)이면 X<Y.
-empty(X)∧empty(Y)이면 X>Y.
-empty(X)∧-empty(Y)∧head(X)<head(Y)이면 X<Y.
-empty(X)∧-empty(Y)∧head(X)>head(Y)이면 X>Y.
-empty(X)∧-empty(Y)∧head(X)=head(Y)이면 rel(X,Y)
=rel(tail(X),tail(Y)).
어떤 언어(파스칼 등)내의 스트링 비교 연산자는 동일한 길이의 스트링상에서만 동작하여, 더 긴 스트링의 길이에 비교하여 더 짧은 스트링을 패딩한다. 따라서, IL은 또한 패딩된 스트링 비교 연산자 EQLP, NEQP, LSSP, LEQP, GTRP 및 GEQP를 갖는다.
모든 스트링 연산자는 표 12에 리스트되어 있다.
부울(Boolean) : 표시적인 데이타 타입과는 달리, 부울 데이타 타입은 유일한 표시를 갖지 않는다. 프로그램 실행중에 부울 값들은 2진수 정수내의 어떤 비트의 값에 의해 명백하게, 또는 취해지는 특정 코드 경로에 의해 암시적으로 표시될 수 있다. 유일한 표시가 없기 때문에 부울 데이타 타입은 IL에 부울 변수를 가질 수 없다. 그러나, 대부분의 소스언어는 표시적인 값의 논리적 해석을 제공하며 많은 것이 논리적인 또는 부울 변수의 선언을 허용한다. 그러므로 연산자는 부울값과 그들 소스언어의 2진 표현 방식에서 변환될 필요가 있다.
LBSET 연산자는 그 최하위 비트를 테스트함으로써 부울로서의 정수를 해석하고, NONZERO 연산자는 전체 정수가 0인지 아닌지를 테스트함으로써 부울로서의 정수를 해석한다. LSBIT 연산자는 정수로서의 부울값을 비트 패턴<00‥00> 또는 <00‥01>로 나타내고, ALLBITS 연산자는 정수로서의 부울값을 비트 패턴<00‥00> 또는 <11‥11>로 나타낸다. 이들 연산자는 다음과 같은 각종 소스언어에서의 부울값의 2진수 표시를 지지한다.
비록 부울값이 표시를 갖지 않아 표준 문자 노드로 표현될 수 없을지라도, 모든 정규 IL 변환을 부울식에 적용할 수 있게 하는 것은 대단히 바람직하다. 그러나 후단(12)은 2개의 특별한 문자 노드를 제공하며, 문자 노드의 어드레스는 전역변수(global variable) GEM $ST_G_TRUE와 GEM $ST_G_FALSE에 포함되어 있다. 이들 문자 노드는 정지 기억기 초기치 설정에 사용될 수 없으나, ILG내의 피연산자로서 사용될 수 있다.
AND 및 OR 연산자를 포함하는 부울식은 두개의 상이의 방식, 즉 완전 계산(ful evaluation) 및 흐름 또는 단락 계산 방식으로 계산될 수 있다. 완전 계산에서, 두개의 피연산자는 완전히 계산되어 실제의 모드값을 산출하고, 그 다음에 이 값은 실제의 모드 결과를 산출하도록 AND 또는 OR 명령에 대해 피연산자로서 사용된다. 흐름 또는 단락계산에서, 제1피연산자가 계산된다. 만약 수식의 값이 제1피연산자의 값에 의해 결정되면, 제2피연산자는 스킵(skip)된다. 그렇지 않다면 제2피연산자는 계산되고 수식의 값은 제2피연산자의 값이 된다.
몇몇 소스언어는 AND 및 OR 식의 완전 계산을 필요로 하고, 다른 소스언어는 단락 계산을 필요로 하거나(또는 단락 계산용의 특별한 연산자를 가지며), 나머지 소스언어는 컴파일러에 대한 선택을 제외하고는 계산의 종류를 특정하지 않는다. 3개의 연산자 세트는 이들 3가지 경우에 대하여 제공된다 ;
(1) LANCD 및 LORC(“논리적 AND 조건”및 “논리적 OR 조건”)는 흐름 부울 연산자이다. 그들은 그들의 제1피연산자를 계산하면 그들의 제2피연산자의 계산을 바이패스할 수도 있다.
(2) LANDU 및 LORU(“논리 AND 무조건”및 “논리 OR 무조건”)은 완전 계산 부울 연산자이다. 그들은 표준 2진 연산자처럼 작용하여 2개의 완전히 계산된 피연산자 식으로부터 결과치를 계산해낸다.
(3) LAND 및 LOR(“논리 AND” 및 “논리 OR”)은 계산의 종류나 피연산자의 차수를 특정하지 않는 CIL 연산자이다. IL 확장동안, 그들은 LANDC과 LORC 또는 LANDU와 LORU 튜플에 의해 교체될 수도 있다. 더욱이 그들이 LANDC와 LORC 튜플에 의해 교체되었을 때, 그들의 피연산들은 그들의 제1피연산자를 계산하는 비용이 그들의 제2피연산자를 계산하는 비용보다 큰 것으로 나타나면 상호 교환될 수 있다.
후단(12)은 LAND, LOR, LANDC 또는 LORC 튜플에 각 피연산자에 속하는 튜플을 식별할 수 있어야만 한다. CIL에서, FLOWMARK 튜플은 이러한 목적을 위하여 사용된다. 이들 튜플중 하나의 제1피연산자와 연관된 모든 튜플은 제2피연산자와 연관된 모든 튜플에 즉식 앞서야만 한다. 여기서 제2피연산자는 부울 연산자 튜플 자체에 즉시 앞서야만 한다. 이들 튜플중 하나의 임의의 피연산자와 연관된 제1튜플은 FLOW MARK 튜플에 의해 즉시 선행되어져야만 한다.
예컨대,
$1 : FLOWMARK ; ! 제1피연산자의 시작
$2 : FETCH(X) ;
$3 : GTR($2,[0]) ;
$4 : FLOWMARK ; ! 제2피연산자의 시작
$5 : FETCH(X) ;
$6 : LSS($5,[0]) ;
$7 : LAND($3,$6 ; ! 연산자 튜플
선택 연산자는 부울 피연산자 값에 따라 임의의 타입의 두 값중 하나를 선택할 것이다. 논리 OR와 AND 튜플처럼 3개의 선택 튜플이 있다 :
(a) SELC는 그 제1피연산자가 참이냐 거짓이냐에 따라 그 제2 또는 제3피연산자만을 평가할 것이다.
(b) SELU는 항상 그 피연산자가 3개 모두를 평가할 것이고, 그 다음에 제2 또는 제3피연산자중 어느 하나의 값을 선택할 것이다.
(c) SEL은 평가의 타입을 특정하지 않는 CIL 연산자이다. 그것은 IL 확장동안 SELC 또는 SELU 연산자에 의해 대체된다.
또한 논리 AND 및 OR 튜플처럼, SEL 및 SELC는 그들 피연산자와 연관된 튜플이 피연산자 치수로 연속되고 FLOWMARK 튜플에 선행할 것을 요구한다.
예컨대,
$1 : FLOWMARK ; ! 제1피연산자의 시작
$2 : FETCH(X) ;
$3 : GEQ($2,[0]) ;
$4 : FLOWMARK ; ! 제2피연산자의 시작
$5 : FETCH(X) ;
$6 : FLOWMARK ; ! 제3피연산자 시작
$7 : FETCH(X) ;
$8 : NEG($7) ;
$9 : SEL($3,$5,$8) ; ! 연산자 튜플
또는
$1 : FLOWMARK ; ! 제1피연산자의 시작
$2 : FETCH(X) ;
$3 : GEQ($2,[0]) ;
$4 : FLOWMARK ; ! 제2피연산자에 대한 코드 없음
$5 : FLOWMARK ; ! 제3피연산자 시작
$6 : FETCH(X) ;
$7 : SEL($3,[0],$6) ; ! 연산자 튜플…제2피연산자 기록
모든 부울 연산자는 표 13에 수록하였다.
실행시간 체킹 ; 연산자를 체크하는 것은 프로그램의 실행중에 어떤 조건이 참인가를 확인하는 것이며, 조건이 참이 아니면 예외를 발생시킨다. ASSERT 연산자를 제외하고, 모든 연산자의 체크는 그들 제1피연산자의 값을 복귀시킨다. 모든 튜플 체킹은 조건이 참이 아니면 신호로 알리도록 된 예외를 특정하는 조건 필드를 가지며, 예외가 신호로 알려진 후 제어가 복귀되는지를 표시하는 필드가 연속될 수 있다. 만약 제어가 예외 후에 체킹 튜플로 복귀하면, 그 체킹 튜플은 예외가 발생하지 않었다면 복귀시켰을 값과 동일한 값을 복귀시킬 것이다. 체킹 연산자는 표 14에 수록되어 있다.
흐름 제어 : ILG(55)는 기본 블럭으로 만들어진다. 기본 블럭은 브랜치 타겟 튜플로 시작해서 브랜치 튜플 또는 흐름 종단 튜플로 종료하는 일련의 튜플들이다. 기본 블럭은 그 시작에서만 진행되고, 그 다음에 원칙적으로 그 안의 모든 코드는 그 종료시에 제어가 그 밖으로 빠져나오기 전에 실행된다(그러나 상술한 조건 계산을 참조.
CILG에서 기본 블럭은 끝과 끝이 연결되어 있다. 기본 블럭의 끝에 있는 브랜치 튜플은 제어가 그 기본 블럭으로부터 LABEL 튜플로 시작해야만 하는 그 다음의 기본 블럭으로 흘러가면 생략될 수도 있다. 유사하게, 기본 블럭의 시작에 있는 LABEL 튜플은 그 기본 블럭에 브랜치가 없으면 생략될 수 있다(즉, 만약 후단이 브랜치 튜플에 의해 선행되지 않는 LABEL을 만나면 후단은 그것에 대해 BRANCH를 삽입하고 ; 만약 후단이 브랜치 타겟 튜플에 의해 후속되지 않는 브랜치 튜플을 만나면 후단은 합성된 라벨 심볼로 LABEL 튜플을 삽입한다). IL 확장 페이즈는 각 기본 블럭에 대한 튜플들 사이의 관계를 나타내는 개별적인 흐름 그래프 데이타 구조와 함께 각 기본 블럭에 대한 튜플들의 순환 리스트를 제작한다.
기본 블럭내에서, 흐름은 은연중에 선형 튜플 순서화를 따른다. 기본 블럭들간의 모든 흐름은 은연중에 흐름 제어 튜플로 표현되기 때문에, ILG의 기본 블럭은 루우틴의 의미에 영향을 미치지 않고 임의의 순서로 배열될 수 있다.
각 기본 블럭의 시작에 있는 브랜치 타겟 튜플은 심볼 테이블내의 엔트리 심볼 노드 또는 라벨 심볼에 대한 포인터를 포함한다. 기본 블럭들간의 제어 흐름은 브랜치 튜플의 속성인 데스티네이션 리스트(destination list)에 의해 표현된다. 데스티네이션 리스트의 각 노드는 라벨 심볼 또는 엔트리 심볼 노드를 지시하며, 이 라벨 심볼 또는 엔트리 심볼 노드는 제어가 그 기본 블럭과 함께 시작하는 기본 블럭에 전달될 수 있는지를 표시하기 위하여 동일 루우틴의 일부 브랜치 타겟 튜플에 의해 또한 지시된다.
브랜치 타겟 튜플은 기본 블럭의 출발을 표시한다. 모든 브랜치 타겟 튜플은 다음과 같은 속성을 갖는다.
브랜치 튜플은 기본 블럭의 종료를 표시하고 그 후속자를 특정한다. 모든 브랜치 튜플은 다음과 같은 속성을 갖는다.
데스티네이션 리스트는 그들의 다음 필드에 의해 함께 연결된 데스티네이션 노드들의 리스트이다. 브랜치 튜플의 데스티네이션 리스트 필드는 이러한 리스트의 제1데스티네이션 노드에 대한 포인터를 포함한다.(데스티네이션 노드는 단 하나의 데스티네이션 리스트에서 발생할 수 있으며, 데스티네이션 리스트는 단 하나의 브랜치 튜플에 의해 지시될 수 있음을 주의하라. 비록 2개의 브랜치가 동일한 데스티네이션을 가지더라도, 여전히 그들은 동일하더라도 구별되는 데스티네이션 리스트를 가져야만 한다) 모든 데스티네이션 노드는 라벨 또는 엔트리 심볼 노드에 대한 포인터를 포함하는 타겟 필드를 갖는다. 데스티네이션 노드는, 그것의 브랜치 타겟 튜플의 라벨 심볼 펄드가 동일 심볼 노드에 대한 포인터를 포함하는 기본 블럭에 대한 제어의 포텐셜 트랜스퍼(potential transfer)를 표시한다. 2종류의 데스티네이션 노드가 있다. 대부분의 종류의 브랜치 튜플은 간단한 데스티네이션 노드를 사용하고, 데스티네이션 리스트의 그 위치에 의거하여 데스티네이션을 선택한다. 그러나 BRSEL 튜플은 선택기 데스티네이션 노드를 사용하고 데스티네이션의 선택기가 튜플의 피연산자 값과 부합하는 데스티네이션을 선택한다. 선택기 데스티네이션 노드는 추가 필드의 로우 테스트와 하이 테스트, 2개의 긴단어 정수를 갖는다. 이것은 만약 피연산자 값이 데스티네이션이 로우 테스트와 하이 테스트 값 사이에 해당하면 피연산자 값과 부합한다.
데스티네이션 리스트와 함께 한 세트의 데스티네이션을 특정하고 튜플 피연산자에 의거하여 그들중의 하나를 선정하는 정규 브랜치 연산자와 달리 간접 브랜치 연산자(JUMP 및 JUMPLOCAL)은 어드레스식(통상 라벨 변수)에 의해 특정된 어드레스로 전달되도록 제어를 발생시킨다. 이들은 goto 할당된 FORTRAN이나 라벨 변수를 통과한 PL/I에 사용되는 연산자이다.
후단은 그것이 루우틴 흐름 그래프를 정확하게 세울 수 있도록 간접 브랜치 튜플이 가능한 데스티네이션을 알게할 필요가 있다. 그러므로 간접 브랜치 튜플은 정규 브랜치 연산자처럼 데스티네이션 리스트를 갖는다. 그러나 그들의 데스티네이션 리스트는 단일 데스티네이션(이것은 JUMP 튜플에 대해 선택적임)만을 포함한다. 이 데스티네이션 노드의 타겟 라벨은 VBRANCH 튜플에 의해 즉시 계속되는 VLABEL 튜플을 식별한다. VBRANCH 튜플의 데스티네이션 리스트는 간접 브랜치의 이 루우틴에서 실제로 가능한 모든 데스티네이션을 일람표로 만든다.
VLABEL 튜플과 VBRANCH 튜플의 조합은 가상 기본 블럭으로서 언급된다. 어떠한 코드도 이것에 대해 항상 발생되는 것은 아니다(이것이 VLABEL 및 VBRANCH 사이에 어떠한 다른 튜플도 존재해서는 아니된다는 이유이다). 이것은 제어가 간접 브랜치로부터 가상 블럭의 임의의 후속자로 통과할 수 있다는 사실을 나타내준다. 이것은 많은 간접 브랜치들이 동일한 세트의 가능한 데스티네이션을 가지면 단일의 가상 기본 블럭은 그들 모두의 가상 데스티네이션을 나타낼 수 있다는 장점을 가지고 있다.
모든 루우틴에는 다른 하나의 가상 기본 블럭이 있다. 이것은 BEGIN 및 ENTRYPTR 튜플로 구성되는 블럭이다. 실행은 항상 ENTRY 튜플에서 시작하기 때문에 이것에 대해 어떠한 코드도 발생되지 않으나, 이것은 후단에 대한 루우틴의 모든 엔트리 포인드를 확인한다.
기본 블럭은 브랜치 튜플 또는 흐름 종료 튜플과 함께 종료될 수 있다. 제어가 흐름 종료 튜플에 도달하면, 이것은 현재의 루우틴을 완전히 떠난다. 흐름 종료 튜플은 현재 루우틴의 데스티네이션으로 제어를 전송하지 않기 때문에 그들은 데스티네이션 리스트 및 타겟 심볼 속성을 가지지 않는다.
JUMP 연산자는 만약 이것이 데스트네이션 리스트를 갖지 않는다면 흐름 종료 연산자인 것이 효과적임을 명심하라. 왜냐하면 그것은 현재의 루우틴에서 어떠한 가능한 데스티네이션도 가지지 않는다는 것을 의미하기 때문이다. JUMPSYMBOL은 CIL에서 알려진 라벨로의 비-로컬 goto를 나타내기 위하여 사용되는 흐름 종단 연산자이다 ; EIL에서는 이러한 비-로컬 JUMP가 그것을 대신할 수 있다.
모든 흐름 제어 연산자는 표 15에 수록되어 있다.
루우틴 호출 및 파라미터 통과 ; 3가지 타입의 연결 규칙이 있다 ; 즉, 제어, 파라미터, 복귀 값이다. “연결 규칙(linkage convention)”이라는 용어는 호출하는 루우틴 및 호출된 루우틴을 서로 적당하게 대화할 수 있게 하는 발생된 코드에 관한 모든 규칙을 말한다. 이들 규칙중의 일부는 코드 발생기(29)에 내장되어 있다. 다른 경우에는 호출하는 호출된 루우틴에 대하여 일관성있게 만들어져야만 하는 선택(choice)이 있다. 이들 선택중의 일부는 셀에 의해 만들어질 것이며(이것이 양 루우틴에 액세스하면) ; 다른 것은 전단(20)에 의해 만들어지고 심볼 테이블(30) 및 ILG(55)에서 코드화 되어야만 한다.
제어 연결 규칙은, 호출된 루우틴의 실행 문맥을 확립하고 제어를 호출 루우틴으로 복귀시키기 위하여, 호출 루우틴으로부터 호출된 루틴으로 제어를 통과시키도록 실행되어야만 하는 명령들을 정의한다. 제어 연결 규칙은 호출된 루우틴에 대한 엔트리 심볼 노드 및 호출 루우틴의 INITCALL 및 CALL 튜플에 의해 결정된다.
그것의 피연산자가 외부 참조가 아닌 엔트리 심볼 노드에 관한 참조인 CALL 튜플은 식별된 호출이며, 심지어 라인에서 호출된 루우틴을 번역하거나 또는 호출된 루우틴의 주문된 카피(copy)를 발생시킬 정도까지 이것에 대한 연결을 선정하는 것은 완전히 자유롭다. 미식별된 호출에 관하여는, INITCALL 튜플의 호출 규칙 필드는 그 호출을 이용하기 위하여 제어 연결 규칙을 특정해야만 한다. 이 필드의 값은 열거된 타입 GEM $ CALLING-CONVENTION으로부터 온 것이어야만 한다. 이들 상수는 다음의 표에 정의되어 있다.
루우틴의 블럭 노드는 표준 엔트리 필드를 가지며, 이 필드는 이 루우틴에 대하여 미식별된 호출에 의하여 호출될 이 루우틴의 카피를 위하여 무슨 제어 연결 규칙이 사용되는지를 특정한다. 이 필드의 값은 그 상수가 다음 리스트에서 정의되는 열거된 타입 GEM $ ENTRY-CONVENTION으로부터 온 것이어야만 한다.
파라미터 연결 규칙은 다른 타입이다. 루우틴 호출은 호출된 루우틴에 대해 이용할 수 있는 인수(argument) 리스트를 만든다. 그 인수 리스트는 약정에 의해 호출된 루우틴과 호출 루우틴 양자 모두에 알려진 위치(그 어드레스가 몇몇 표준 레지스터에 포함된 메모리 블럭내의 레지스터 또는 위치)에 있는 스칼라 값(종종 어드레스)의 집합이다.
호출된 루우틴의 형식상의 파라미터는 파라미터 플래그 세트인 변수 심볼 노드에 의해 표현된다. 파라미터 심볼과 연관된 어드레스는 호출 루우틴에 의해 특정된 기억 위치이거나 호출 루우틴에 의해 통과된 데이타의 카피를 포함하는 로컬 기억 위치이다(“어드레스”는 실제로 레지스터를 특정할 수 있음을 기억하라). 이것은 인수 리스트로부터 유래한 것이며, 메카니즘과 후술하는 파라미터 심볼의 의미 플래그로부터 유래한 것이다.
파라미터는 파라미터 변수와 연관된 어드레스가 호출 루우틴에 의해 통과된 기억 위치(실제의 기억 위치)의 어드레스이면 바인드 의미론(bind semantics)을 가진다. 이것은 만약 컴파일러가 호출된 루우틴(로컬 기억 위치)에서 이것에 대한 기억을 할당하고, 필요할 때 실제의 기억 위치와 로컬 기억 위치 사이의 카피를 발생시키면 카피 의미론을 가진다(바인드 의미론과 함께 파라미터의 로컬 기억 위치는 그 실제의 기억 위치와 동일하다.
컴파일러는 표 10-3에 수록된 플래그와 루우틴내의 파라미터의 관용적인 패턴에 근거하여 파라미터에 관한 카피 의미론을 사용하는지 또는 바인드 의미론을 사용하는지를 선택할 것이다. “별명(alias) 효과들”은 CTO.70,데이타 액세스 모델에 언급되어 있다. 간략하게 설명하면 그들은 실제의 기억 위치가 파라미터 심볼을 통과하는 것을 제외한 다른 것에 액세스될 수 있는 통로이다. 이것은 실제의 기억 위치일 수 있는 비-로컬 변수에 대한 직접 참조, 디레퍼런스 효과(dereference effects), 실제의 기억 위치에 액세스할 수 있는 다른 루우틴에 대한 호출을 포함한다.
표 17은 그들이 각종 소스언어에 대해 설정될 때의 파라미터 의미 플래그의 사용을 나타낸 것이다.
파라미터 메카니즘은 어떤 호출 루우틴이 호출된 루우틴으로 통과되기를 원하고 무엇이 인수 리스트에 실제로 기억되는지 그들 사이의 관계를 특정한다. 인수튜플은 메카니즘을 특정하는 메카니즘 필드를 가지며, 그 메카니즘에 의해 이 인수는 통과될 것이다. 이들 필드의 값은 그 상수가 표 18에 수록되어 있는 열거된 타입 GEM$ MECHANISM으로부터 와야만 한다.
만약 파라미터 변수의 미지의 크기의 플래그가 거짓이면, 그 파라미터의 크기는 컴파일 시간에서 알려지며 그 크기 필드에 의해 특정된다. 만약 미지의 크기의 플래그가 참이면 그 파라미터의 크기는 컴파일 시간에서 알려지지 않는다. 미지 크기의 파라미터의 크기는 만약 그것이 어레이, 스트링 또는 어드레스 및 길이(길이 파라미터와 연관된 참조)메카니즘을 가지면 실행 시간에서 결졍될 수 있다. 분리 길이 단어가 어드레스 및 길이 메카니즘과 함께 통과되고 파라미터가 군 데이타 타입을 가지면, 길이 인수는 바이트로서가 아니라 요소(비트 또는 문자)의 파라미터 크기로서 해석된다. 더욱이, 파라미터가 그 스트링 표시방식이 변화하는 등의 문자 스트링이면, 그 크기는 스트링의 현재의 크기가 아니라 최대 크기이며, 또한 스트링의 테스트 부분에만 공급되고 스트링 길이 단어 또는 널 종결기를 필요로 하는 공간에는 인가되지 않는다. 파라미터는 컴파일러가 얼마나 많이 카피하는지를 알지 못하는 한 카피 의미론을 가질 수 없다는 점에 주의하라. 만약 실제의 파라미터 크기가 컴파일 시간에서 알려져 있지 않고 실행 시간에서 컴파일러에 의해 계산될 수 없으면, 전단은 바인드 의미론의 사용을 담보하기 위하여 파라미터의 머스트 바인드 플래그(must bind flag)를 설정해야만 한다.
다른 타입은 복귀값 연결 규칙이다. 호출된 루우틴은 정보를 두가지 방법으로 그 호출기에 복귀시킬 수 있다. 첫번째 방법은 출력 파라미터를 사용하는 방법이다. 이것은 값보다는 메카니즘과 함께 통과되는 변수이므로 호출된 루우틴은 하나의 값을 그 안에 기억할 수 있다. 두번째 방법은 복귀값으로 하는 방법이다. 복귀값은 호출된 루우틴에 의해 계산되어 호출기로 “복귀”되는 값이며, 여기에서 복귀값은 특별한 결과 튜플을 통해 수식의 값으로서 이용 가능하게 된다.
스칼라 값은 레지스터로 복귀될 수 있다. 예컨대, 거의 모든 우리의 언어는 표준 레지스터에서 산술 기능 값을 복귀시킨다 ; 그리고, BLISS “출력 파라미터” 특징은 루우틴이 임의 레지스터내에 값들을 복귀시킬 수 있도록 한다.
스트링을 복귀시키기 위한 루우틴에 관하여는, 복귀값에 대한 일시적인 버퍼를 할당하고, 그 어드레스를 호출된 루우틴으로 통과시키기 위한 인수 리스트의 튜플과, 복귀값을 상기 버퍼에 기억시키기 위한 호출된 루우틴의 튜플과, 또 버퍼로부터 그 값을 검색하기 위한 호출기의 튜플이 존재하여야만 한다.
복귀된 스트링의 크기가 호출된 루우틴에 의해 결정되는 경우, 호출기는 그 결과가 얼마나 큰지를 미리 알 수 없기 때문에 그 결과에 대한 공간을 정확히 할당할 수 없다. 표 19에 수록된 메카니즘은 이러한 가능성을 제공한다. 이들 메카니즘은 특별한 튜플을 통하여 제공된다. 그러나 그들의 유용성은 타겟 환경의 호출 표준에 좌우된다.
호출기는 (a) 호출된 루우틴이 고정된 버퍼에 의해 하나의 값을 복귀시킬 것을 요구할 수도 있고 ; (b) 호출된 루우틴이 스택상에 하나의 값을 복귀시킬 것을 요구할 수도 있고 ; (c) 호출된 루우틴이 동적 스트링에 의해 하나의 값을 복귀시킬 것을 요구할 수도 있으나, 만약 호출된 루우틴이 그렇게 선택하면 스택상에 복귀된 스트링을 받아들일 수 있다. 호출된 루우틴은 고정된 버퍼 또는 호출기가 이것을 필요로 하면 스택에 의해 동적 크기 결과를 복귀시키도록 항상 준비되어 있어야만 한다. 이것은 또는 동적 스트링 또는 호출기가 동적 스트링에 의한 결과를 요청하면 스택에 의해 결과를 복귀시키도록 준비되어 있어야만 한다. CIL에서 루우틴 호출의 표시 방식이 이제 고려되어야할 것이다. 절차나 기능을 호출하는 것에 포함된 많은 분명한 운영이 있다. 다음 단계중 어떤 것은 필수적이다 ;
(1) 인수 리스트에 대한 공간을 할당한다.
(2) 패스-바이-값(pass-by-value) 피연산자 식에 대한 공간을 할당한다.
(3) 서술자에 대한 공간을 할당한다.
(4) 인수 서술자를 만든다.
(5) 결과 값에 대한 공간을 할당(결과값 또는 출력 인수는 호출후까지 존재하지 않는 인수이다. IL에서 기능은 결과값과 함께 절차로서 처리될 것이다..
(6) 인수 리스트를 만든다.
(7) 루우틴을 호출한다.
(8) 인수, 설명자, 인수 리스트에 할당된 공간을 해제한다.
(9) 호출로부터 결과값을 얻는다.
(10) 결과값에 대해 할당된 공간을 비워둔다.
IL에서 취한 일반적 전략은 호출을 하는 것에 포함된 다른 운영에 관한 각각의 연산자를 제공하기 위한 것이나, 이들은 특정된 패선에 함께 연결될 것을 요구하기 위한 것이다. IL에서의 루우틴 호출은 다음의 것으로 구성되어 있다 ;
1. 호출을 만들 액션 시리즈의 시작을 플래그하는 INITCALL 문장.
2. 인수 리스트를 구성할 인수 및 일시적 할당 문장의 시리즈.
3. 호출된 루우틴에 대한 제어의 전송에 실제로 영향을 미치는 명령문(CALL 또는 BPCALL).
4. 호출의 복귀값을 액세스 가능하게 만드는 결과 튜플의 시리즈.
INITCALL 및 명령문은 강제적이다 ; 인수 리스트 및 결과 튜플은 선택적이다. 호출에 포함된 모든 튜플은 동일한 기본 블럭에서 발생하여만 하며, 어떤 결과 튜플도 사이에 끼어든 튜플이 없이 즉시 호출 튜플을 따라야만 한다. 하지만, INITCALL과 호출 사이에서 무슨 튜플이 발생할 수 있는가에 관하여는 다른 어떠한 제약도 없다. 심지어 루우틴 호출에 대한 IL은 다른 호출에 대한 인수 리스트내에 포함될 수도 있다.
인수 리스트를 구성하는 것은 그 자체의 인수 리스트에 대한 인수의 어드레스 및 설명자에 대한 통과될 값을 유지하기 위한 템포러리에 대한, 그리고 출력 인수에 대한 공간을 할당하는 것을 포함한다. 이것은 또한 할당된 공간을 초기화하는 것을 포함한다. 이들 활동은 인수 튜플과 함께 IL에서 특정된다. 모든 인수 튜플은 ARG로 시작하는 명칭을 가지며, 표 20에 그 속성이 수록되어 있다.
호출 루우틴이 통과하는 값을 가지는 경우, 그것은 그 이름이 ARGVAL로 시작하는 인수 튜플들중의 하나를 사용한다. 이들 튜플과 함께, 실제 인수 값은 인수 튜플의 피연산자로서 특정된다. 이것이 인수가 값 메카니즘을 사용하여 통과된다는 것을 필연적으로 의미하는 것이 아님을 주의하라. 메카니즘이 값이라면, 피연산자 값은 바로 인수 리스트내로 기억된다 ; 그렇지 않다면, 일시 기억이 할당되고, 피연산자 값은 일시 기억내로 기억되며, 그리고 일시 기억은 참조 또는 서술자에 의해 통과된다.(이것은 BLISS의 %REF와 비슷하다). 값 메카니즘은 스칼라 타입을 갖는 ARGVAL 튜플, 및 컴파일 시상수 크기를 갖는 ARGVALA 튜플로 단지 지지될 것이다.
호출 루우틴이 통과하는 기존 기억 위치의 어드레스를 가지는 경우, 그것은 그 이름이 ARGADR로 시작 하는 인수 튜플중의 하나를 사용한다. 이들 튜플과 함께, 실제 기억 위치의 어드레스는 인수 튜플의 피연산자로서 특정된다. 따라서 값 메카니즘은 이들 튜플과 함께 사용될 수 없다. 인수 리스트에서 이들 튜플중의 하나의 발생은 호출된 루우틴이 현재 루우틴에 대해 알려진 기억 위치로부터 판독하거나 또는 그 위치에 기록하도록 하기 때문에, 이들 튜플은 종속성과 측면 효과를 가질 수 있으므로 오프셋, 효과, 효과2, 및 기본 심볼 필드를 가지는데, 상기 기본 심볼 필드는 호출된 루우틴이 기억 위치로부터 판독할 수 있고/있거나 그 위치에 기록할 수 있다고 컴파일러가 가정해야만 하는지를 지시하는 모든 메모리 참조 튜플내에서, 특별한 플래그 팜(parm)이 판독되고 팜이 기록되는 것과 마찬가지로, 사용되는 것이다.
인수 튜플이 일반 메카니즘을 특정하는 경우, 서술자에 대한 공간을 할당하고 그 기본 어드레스 필드를 채우기 위하여 코드가 발생된다. 전단은 서술자에서 초기화 되도록 되어있는 임의의 다른 필드를 명백하게 특정해야만 한다. 이것은 DSCFIELD 튜플을 사용한다. 이 DSCFIELD 튜플은 일반적인 메카니즘을 가진 선행하는 인수 튜플을 되돌아가서 참조하고, 그리고 그 인수에 대해 할당된 서술자의 필드내로 기억되는 값을 특정한다.
인수 블럭의 구성 : 일부 RTL 연결은 인수의 집합이 인수 블럭내에서 통과될 것을 요구할 수 있다. 이 인수 블럭의 어드레스는 통상의 참조 파라미터처럼 RTL 루우틴으로 통과된다. 이것은 3개의 특별한 튜플을 사용하여 달성된다.
(a) ARGBLOCK은 스택상에 특정 크기의 블럭을 할당하고 그 어드레스를 호출된 루우틴으로 통과시키는 인수 튜플이다. 그 블럭은 BLKFIELD 튜플을 사용하여 초기화될 수 있다.
(b) BLKFIELD 튜플은, 이것이 일반적 서술자 메카니즘을 가진 임의의 튜플 대신 선행하는 ARGBLOCK 튜플을 참조하는 것을 제외하고는, DSCFIELD 튜플과 같다. 이것은 하나의 값을 인수 블럭의 필드내로 기억시킨다.
(c) ARGDEFINES는, 이것이 어떠한 코드도 발생시키지 않는다는 것을 제외하고는, 인수 튜플과 같다. 이것은 전단이 정규의 인수 튜플과 연관되지 않은 인수와 같은 측면 효과를 특정하게 된다. 특히, 이것은 인수 블럭을 통해 통과된 인수와 연관된 효과를 표시하기 위하여 사용될 수 있다.
루우틴이 군 값을 복귀시키기 위해서는, 그 값을 그 호출기에 의해 할당된 위치에 기억시켜야만 한다. 그 이름이 ARGTMP로 시작하는 튜플은 특정 크기의 기억 블럭을 할당하며 그 어드레스를 호출된 루우틴으로 통과시킬 것이다. 그들은, ARGADR 튜플이 기존 기억 블럭의 어드레스를 통과하고 그리고 ARGTMP 튜플이 그 호출에 특별히 할당된 일시 기억의 어드레스를 통과하는 것을 제외하고는, ARGADR 튜플과 동일하다.
ARGBUF, ARGSTK 및 ARGDYN 튜플은 일시 기억을 할당할 것이고 또한 동적 스트링 복귀값을 획득하기 위해 필요한 특별한 서술자를 통과할 것이다. 이들 튜플은 모든 보통의 인수 튜플 속성을 가지지만, 그들의 메카니즘 속성은 그 메카니즘이 동적 복귀값 메카니즘의 사용에 의해 함축되어 있기 때문에 무시된다.
그 명칭이 RESULT로 시작하는 튜플은 루우틴 호출로부터의 복귀값을 호출 루우틴내에서 액세스 가능하게 만들 것이다. 그들 효과는 출력 파라마터들을, 그들이 호출된 루우틴에 의해 복귀되어 졌던 일시 기억 위치 또는 레지스터로부터 보다 지속적인 일시 기억으로 이동시키는 것이다. 결과 튜플의 값은 단순히, 그것이 검색했던 복귀값의 값이다. 호출에 대한 모든 결과 튜플은 호출 튜플을 즉시 뒤따라야만 한다.
바운드(bound) 절차 호출 : 바운드 절차 값 또는 BPV는 미지의 루우틴을 호출하기 위해 필요한 정보를 나타낸다. 루우틴은 다른 루우틴의 할당된 변수를 스택하기 위해 엎레벨(uplevel)의 참조를 포함하기 때문에, 바운드 절차값은 호출될 루우틴의 코드 어드레스 뿐아니라 이것에 대한 정적 연결을 구성할 충분한 정보를 통합하여만 한다.
불행하게도 BPV는 상이한 소프트웨어 구조(architecture)에서는 상당히 다르게 취급된다. 즉 그들이 어떻게 발생되고, 어떻게 표시되며, 어떻게 호출되고, 심지어 얼마나 큰지에 따라 다르게 취급된다. 그러므로 컴파일러는 변함없는 표시를 제공하려고 시도하지 않을 것이다. 대신에, 전단은 타겟 소프트웨어 구조에 따라 다른 코드를 발생시키도록 기대될 것이다.
(a) VAX와 MIPS 소프트웨어 구조에서, BPV는 단순히 코드 어드레스 및 문맥값이며, 바운드 절차 호출은 문맥값을 특정 레지스터에 로드하고 코드 어드레스에 대해 호출을 행함으로써 수행된다. 그러므로 전단은 한쌍의 독립 어드레스값으로서 BPV를 나타내는데 책임이 있을 것이다. 코드 어드레스는 BPLINK 튜플과 함께 획득된다. BPV에 대한 호출은, 문맥값이 그 구조의 정적 연결 레지스터에서의 특별 레지스터 인수로서의 값에 의해 통과됨과 아울러, 그 어드레스 피연산자가 코드 어드레스 값인 CALL로 표시된다.
(b) RISC 머신에 관하여는, 모든 절차는 약간의 추가 정보와 함께 코드 어드레스를 포함하는 서술자에 의해 표시되며, BPV는 실행 시간에 구성되어 문맥 포인터를 로드하고 실제(real) 루우틴을 호출하기 위하여 RTL 루우틴의 어드레스와 문맥 포인터를 포함하는 단순히 특별한 서술자의 어드레스이다. 전단은 이러한 서술자 자체에 대한 공간을 할당해야만 할 것이고 또한 이것을 안에 채우기 위하여 BPVAL 튜플을 사용하여야만 할 것이다. 그 다음에 BPV는 서술자의 어드레스에 의해 표시되고, BPV에 대한 호출은 그 어드레스에 대한 호출에 의해 나타내어져야만 한다.
후단(12)은 어떤 파라미터가 루우틴의 각 엔트리 포인트에 대해 있는지를 알 필요가 있다. 전단(20)은 그 엔트리 포인트의 파라미터 리스트를 나타내는 (그들의 다음 필드에 의해 연결된)파라미터 노드의 리스트의 최초의 노드와 최종 노드를 지시하도록 각 엔트리 심볼 노드의 파라미터 리스트와 파라미터 리스트 테일(tail) 필드를 설정함으로써 이것을 달성한다.
각 파라미터 노드는 엔트리 포인트를 포함하는 루우틴의 파라미터 심볼 노드와 인수 위치를 지시하는 심볼 필드와, 그들이 인수 튜플에서 행하는 것과 동일한 의미를 갖는 특정 레지스터 필드와, 패스 바이 레지스터(pass by register)를 갖는다(표 20 참조). 따라서 파라미터 노드의 리스트는 엔트리 포인트의 모든 파라미터와 그들이 엔트리 포인트의 인수 리스트내 어디에서 발생하는지를 식별한다. 파라미터 심볼은 하나 이상의 파라미터 리스트에서, 아마도 각각에 대하여 상이한 인수 위치로, 발생할 수도 있음에 주의하라. 그러나 파라미터 노드는 메카니즘 필드를 가지지 못하는데, 그 이유는 그 메카니즘이 특정 인수 리스트내에서의 발생이라기 보다는 파라미터 심볼의 속성으로서 간주되기 때문이다.
RETURNREG 튜플은 특정 레지스터에 스칼라 값을 복귀시키며, RETURNSTK와 RETURNDYN 튜플은 PRISM 호출 표준에서 제공된 동적 스트링 복귀 메카니즘중의 하나를 사용하여 스트링 값을 복귀시킨다. 인수 일시 기억을 통하여 값을 복귀시키는 것과 하나의 값을 하나의 통상적인 출력 파라미터에 기억시키는 것 사이에는 어떠한 차이도 없기 때문에, 인수 일시 기억을 통하여 값을 복귀시키기 위해 호출된 루우틴에 대하여 어떤 특별한 튜플도 필요하지 않음을 주의하라.
파라미터 심볼과 연관된 어드레스는 파라미터의 로컬 기억 위치의 어드레스이다. 호출된 루우틴은 DESCADDR 튜플을 사용함으로써 일반적 서술자 메카니즘과 함께 파라미터에 대한 서술자의 어드레스를 획득할 수 있다. 이것은 만약 그 크기가 인수 리스트에서 이용가능하면(서술자에서 또는 개별적인 크기의 파라미터에서) SIZE 튜플을 이용하는 미지의 크기 파라미터의 실제 크기를 획득할 수 있다.
루우틴 호출에 포함된 모든 연산자는 표에 수록되어 있다.
기억 할당 및 영역화 : 어휘 블럭은 선언의 세트, 예컨대 루우틴, 서브 루우틴, 기능 또는 시작 및 종료 블럭 등이 타당한지에 관한 소스 프로그램의 범위이다. 심볼의 표에서 루우틴의 어휘 구조는 그 루트가 루우틴 블럭 노드인 영역 블럭 노드의 트리에 의해 표현된다. ILG에서의 각 기본 블럭은 단일 어휘 블럭에 속하는 코드를 포함한다. 기본 블럭의 시작시에 브랜치 타겟 튜플은 심볼의 표에서 대응 블럭 노드를 지시하는 영역 블럭 필드를 갖는다. 루우틴에서 매 어휘 블럭은 독특한 영역 엔트리 기본 블럭을 가져야만 하며, 이것은 제어가 그 어휘 블럭의 외부에 있는 임의의 기본 블럭으로부터 통과할 수 있는 어휘 블럭에 있는 기본 블럭일 뿐이다. 이 영역 엔트리 기본 블럭은 브랜치 타겟 튜플내의 블럭 엔트리 플래그에 의해 식별된다.
CIL에서 변수 심볼에 대한 참조는 항상 기억위치(또는 레지스터의 명칭)의 어드레스를 생기게 한다.
1. 정적 변수는 그 기억 등급이 정적, 전역적 참조 또는 보전적인 것이다. 정적 변수는 번역 시간에서 일부 PSECT에 위치하므로 이러한 변수에 대한 모든 참조는 동일한 위치를 참조할 것이다.
2. 로컬 변수는 그 기억 등급이 자동, 스택로컬, 레지스터 또는 선택된 레지스터이고, 그 미지 크기의 플래그가 거짓인 것이다. 로컬 변수는 그들 어휘 영역의 단일 실행동안에만 존재하며, 만일 그들 어휘 영역의 다중 사례가 동시에 실행될 수 있으면 다중 사례를 가질 수도 있다. 그들은 번역 시간에서 레지스터로 할당되거나 그들 루우틴의 스택 프레임에 있는 기지의 위치로 할당된다.
3. 동적 변수는 로컬 변수와 동일한 기억 등급을 가졌으나 그 미지의 크기 플래그가 참인 것이다. 로컬 변수처럼 동적 변수는 그들 어휘 영역의 다중 사례(multiple instance)가 동시에 실행될 수 있으면, 다중 사례를 가질 수 있다. 그들은 CREATE 튜플에 의해 실행 시간에서 스택상에 할당되며, 후단에 의해 발생된 관련 포인터 변수를 통하여 액세스된다.
4. 카피 의미론을 갖는 파라미터는 그들 미지 크기의 플래그의 설정에 따라 로컬 또는 동적 변수처럼 행동한다.
5. 바인드 의미론을 갖는 파라미터는 호출된 루우티내에서 전혀 할당되지 않는다. 그들은 실제의 기억 위치 어드레스를 유지하기 위하여 후단에 의해 발생된 관련 포인터 변수를 통해 액세스된다.
어휘 블럭에서의 튜플은 그 어휘 블럭내에서 또는 심볼 테이블 블럭 트리의 임의의 선조내에서 선언된 어떠한 변수도 참조할 수 있다. 물론 현재의 루우틴내의 변수를 참조하는 것에 대한 문제점은 전혀 없다. 또 다른 루우틴의 정적 변수는 직접 참조될 수 있다. 다른 루우틴의 로컬 및 동적 변수는 변수가 선언되는 스택 프레임을 위치시키기 위하여 “정적 체인(chain)”을 필요로 한다. 그러나 후단(12)은, 만약 전단이 그 루우틴 블럭과 변수에 정확하게 주석을 단다면, 정적체인을 만들고 사용하기 위한 코드를 발생시키는데 완전한 책임이 있다.
몇가지 종류의 동적 스택 할당이 있다.
1. 동적 변수에 대한 스택 기억은 CREATE 튜플에 의해 할당되며, 제어가 CREATE 튜플과 동일한 어휘 블럭에 있지 않는 기본 블럭으로 통과될 때까지 CREATE 튜플의 실행으로부터 존재한다(이것은 동적 변수에 대한 CREATE 튜플이 기본 블럭에 할당되어야만 한다는 것을 의미한다. 이 기본 블럭의 영역 블럭은 변수가 선언된 블럭이다. 그렇지 않다면, 이것의 동적 기억은 변수가 어휘적으로 영역내에 존재하는 동안 해제될 것이다).
2. 미지 크기의 카피 파라미터에 대한 스택 기억을 할당하기 위한 코드는 ENTRY 튜플을 뒤따라서 즉시 발생된다. ENTRY 튜플이 주 루우틴 블럭에 존재해야만 하기 때문에, 이 기억은 루우틴이 복귀할 때까지 존재한다.
3. 동적 임시 기억은 군 수식(aggregate expression)의 값을 유지하기 위하여 후단에 의해 발생될 수도 있다. 그것은 적어도 그 값을 사용하는 튜플의 실행 때까지 그 값을 발생시키는 튜플의 실행으로부터 존재하게 된다.
4. 스택 공간은 군 ARGVALx 튜플에 대한 인수값을 유지하기 위해 할당되며, CALL 튜플의 실행시까지 ARGVALx 튜플의 실행으로부터 존재하게 된다.
5. 스택 공간은 ARGTMPx 튜플에 대한 복귀값을 유지하도록 할당된다. 이것은 복귀값을 인출하는 RESULTx 튜플의 계산시까지 ARGTMPx 튜플의 실행으로부터 존재하게 된다.
본 발명이 특정 실시예와 관련하여 설명되었으나, 이 설명을 제한하기 위한 의미로 해석해서는 안된다. 본 발명의 다른 실시예와 함께 각종 변형 실시예들은 본 명세서를 참조로 하면 당업자에게는 명백하다. 그러므로 첨부된 청구항은 본 발명의 진정한 범위에 해당하는 수정예 및 실시예를 망라할 것이다.
[표 1]
[표 2]
[표 3]
[표 4]
중간 언어 정의 파일
[표 5]
[표 6]
[표 6a]
[표 7]
[표 8]
[표 9]
[표 9a]
[표 10]
[표 11]
[표 11a]
[표 11b]
]
[표 11c]
[표 12]
[표 12a]
[표 13]
[표 14]
[표 15]
[표 16]
[표 17]
[표 18]
[표 19]
[표 20]
[표 21]
[부록]
[해석자(interpreter) 제어 동작
다음의 동작들은 동작 해석자의 실행 흐름을 제어한다.
ACTIONS(<result-var-list> ; <temporay-var-list>)는 템플리트(template)의 일련의 동작의 시작을 나타낸다. 이것은 피연산자 변수를 할당하므로 템플리트에서의 처음 동작이어야만 한다. 두개의 var-lists의 내용은 템플리트의 레스트(rest) 동안 피연산자 변수를 명명하기 위해 사용된 콤마로 분리된 일련의 식별자이다. 이들 var-lists중 하나는, 템플리트가 결과 피연산자나 일시 기억 피연산자를 사용하지 않는 경우, 비어있을 수 있다. result-var-list의 식별자는 결과 피연산자의 이름이다. 빈 콘텍스트의 ILG노드는 0 결과 피연산자를 가지며, 반면에 대부분의 다른 수식은 1결과 피연산을 갖는다. 예외(exeption)로는, 2개 또는 3개의 피연산자(스트링 몸체(body)를 어드레스하기 위한 1개, 스트링 길이에 대한 1개 및 스트링 몸체를 유지하기 위한 1개)를 필요로 하는 스트링 결과와, 2개의 피연산자(실수 성분에 대한 1개 및 허수 성분에 대한 1개)를 필요로 하는 복소수 결과가 포함된다.
DELAY는 비지연 동작의 종료 및 지연 동작의 개시를 나타낸다. DELAY 동작이 해석될때, 현재 템플리트의 처리는 대응 ILG 서브트리(subtree)가 부모 서브트리(parent subtree)의 잎(leaf)처럼 사용될 때까지 보류된다. 부모 서브트리의 템플리트가 대응 잎을 지연시키지 않을때, 해석은 지연 동작 다음의 동작으로 계속된다.
EXIT는 동작 시퀀스의 해석을 종결한다. EXIT 동작을 해석함으로써 결과 피연산자가 복귀되어지고, 잔여 피연산자 변수 및 로컬 TNs가 해제되어지며, 이 동작 시퀀스를 지연시키지 않은 템플리트로 해석이 다시 시작한다.
END-ACTIONS은 동작 시퀀스의 종결을 나타낸다. 이것은 해석되지 않으므로 사실상 동작이 아니다. END-ACTIONS 오퍼레이션은 동작 시퀀스의 어휘적으로 최종 성분으로 되어야 한다. 상기 오퍼레이션은 ACTION 오퍼레이션에서 선언된 피연산자 식별자 범위의 종결을 뜻한다.
UNDELYA(leaf, opr1, opr2,…)는 지정된 패턴 “잎(leaf)”의 지연 콘텍스트 동작을 처리되게 한다. 잎의 결과 피연산자는 피연산자 변수들 “opr1”, “opr2”등으로 카피된다. 카피된 피연산자의 수는 잎의 본형에서 결과가 피연산자의 수와 같아야만 한다.
LABEL(name)은 동작 시퀀스내의 현위치에 라벨을 붙이도록 “명칭”을 발생시킨다.
GOTO(name)는 해석자가 “명칭”에 의해 지정된 라벨의 다음에 오는 동작에서 처리를 브랜치하고 계속 하도록 한다.
[TN 할당 및 수명시간 동작]
INCREMENT-LON( )은 TNs의 수명시간을 결정하기 위해 사용되는 선형 오더수 클럭 변수(Linear Order Number clock variable)를 증분시킨다.
USE(operand)는 지정된 피연산자 변수가 참조되게 한다. 이 동작은 피연산자가 사용되어 수명시간이 적절히 연장되도록 하는 템플리트내의 최종 위치를 표시하기 위해 사용된다.
ALLOCATE-PERMANENT는 “크기” 바이트의 영구 클라스(class) TN이 지정된(operand, Size) “피연산자” 변수에 의해 창출되고 참조되어지도록 한다. “크기” 파라미터가 빠져있는 경우, TN의 크기는 현재 템플리트의 결과 데이타 타입에 의해 결정된다. 이 동작은 단지 CONTEXT 통과 동안 TN을 창출할 뿐이다. TNBIND 및 CODE 통과동안 이 TN이 어떻게 액세스되느냐에 대한 설명은 SAVE-TN 동작을 참조하라.
ALLOCATE DELAYED는 “크기” 바이트의 지연된 클라스 TN이 지정된 “피연산자”(operand, Size) 변수에 의해 창출되고 참조되도록 한다. “크기” 파라미터가 빠져있는 경우, TN의 크기는 현재 템플리트의 결과 데이타 타입에 의해 결정된다. 이 동작은 각각의 CONTEXT, TNBIND 및 CODE 통과동안 TN을 창출한다. 이 동작은 비지연된 동작을 해석하는 동안 실행되지 않을 수 있다. 이 TN의 수명시간은 이 TN을 사용하는 결과가 사용될때 종결된다.
ALLOCATE -LOCAL은 “크기“”바이트의 로컬 클라스 TN이 지정된 “피연산자” (operand Size) 변수에 의해 창출되고 참조되도록 한다. “크기” 파라미터가 빠져있는 경우, TN의 크기는 현재 템플리트의 결과 데이타 타입에 의해 결정된다. 이 동작은 각각의 CONTEXT, TNBIND 및 CODE 통과동안 TN을 창출시킨다. 이 TN의 수명시간은 그것의 창출과 마찬가지로 동일 템플리트에서 종결되어야만 한다.
FORCE-REGISTER(operand)는 “피연산자” 변수로 지정된 TN이 메모리내에 있지 않아야 하는 것처럼 표시되게 한다. 통상 이것은, TN이 할당되지 않은 경우에 어떤 레지스터도 이용할 수 없는한, 레지스터에 할당하는 것을 의미한다.
FORCE-MEMORY “피연산자” 변수로 지정된 TN이 레지스터에 있지(operand)는 않아야 하는 것처럼 표시되게 한다. 이것은 스택위치에 대한 할당을 보증한다.
MUST-ALLOCATE는 “피연산자” 변수로 지정된 TN이 할당되어야 하는 것처럼(operand) 표시되게 한다.
Note : 이들 3개의 조건이 모순되고 전부 이행될 수는 없기 때문에 동일한 TN상에서 FORCE-REGISTER, FORCE-MEMORY 및 MUST-ALLOCATE 3개 모두를 행하는 것은 에러이다.
REFERENCE “피연산자 1”이 레지스터로 할당되면(operand1, operand2) “피연산자 2”는 동일 레지스터에 할당되고, 그렇지 않으면, “피연산자 2”는 “피연산자 1”에 독립적으로 할당된다. “피연산자 1”과 “피연산자 2”가 모순되는 수명시간을 가질지라도, “피연산자 2”를 “피연산자 1”과 동일한 레지스터로 강제하는 일이 발생할 수 있다(PREFERNCE 동작의 “강제적” 선택과는 반대되는 “조언적” 선택에 대한 MOVE_VALUE 동작을 참조).
INCREMENT_COST(number, operand)는 “피연산자”에 의해 지정된 TN의 비할당 비용을 총 “number” 만큼 증가시킨다.
RESERVE-RO(number)는 연속적인 레지스터 “수”가 레지스터 0로 시작하여 남겨지도록 한다.
TEST-MEMORY(operand, label)는 지정된 “피연산자” 변수에 의해 참조된 TN을 테스트한다. 상기 TN이 메모리내에 있으면, 동작 해석자는 지정된 “라벨”로 브랜치한다. CONTEXT 및 TNBIND 통과중에, 이 동작은 비할당된 TN들이 그들 상에서 수행된 FORCE_MEMORY를 갖지 않는 한 그들이 메모리내에 있지 않는 것으로 가정한다.
TEST-REGISTER(operand, label)는 지정된 “피연산자” 변수에 의해 참조된 TN을 테스트한다. 상기 TN이 레지스터내에 있으면 동작 해석자는 지정된 “라벨”로 브랜치한다. CONEXT 및 TNBIND 통과중에, 이 동작은 FORCE_MEMORY가 TN상에서 수행되어지지 않는 한 비할당된 TN들이 메모리내에 없는 것으로 가정한다.
[ILG 로드 및 저장 동작 ]
LOAD-LITERAL(Node, operand)는 템플리트 패턴에 의해 정합된 지정 “노드”의 리터럴 값을 지정된 “피연산자” 변수내로 로드한다. “노드”가 LITREF가 아닌 경우 이것은 에러이다.
SAVE-TN(operand, Node, field)는 참조를 “피연산자” 변수에 의해 지정된 영구 클라스 TN으로 저장한다. CONTEXT가 통과하는 동안 TN 포인터는 템플리트의 지정된 “노드”에 의해 정합된 ILG 튜플의 성분 “필드”내에 저장된다. TNBIND 및 CODE가 통과하는 동안 이 정보는 지정된 “노드”의 지정된 “필드”로부터 인출된다. 모든 영구 클라스 TN은 CONTEXT 통과중에 적당한 ILG 필드내에 저장되어야만 하므로, 동일한 TN은 TNBIND 및 CODE 통과동안 위치될 수 있다. 지연된 클라스 및 로컬 클라스 TN은 각각의 통과마다 재창출되므로 결코 저장되지 말아야 한다.
SAVE-OPERAND(operand, node, field-reg, field-base)는 지정된 “피연산자” 변수의 위치를 저장한다. 이 정보는 템플리트의 지정 “노드”에 의해 정합된 ILG 튜플내에 저장된다. 레지스터 값은 성분 “field reg”내에 저장된다. 어떤 레지스터 값들은 어떤 할당도 발생하지 않았다는 것 또는 피연산자가 레지스터 대신 스택상에 할당된 것을 코드화 한다. 피연산자가 스택상에 할당되어진 경우, 스택 오프셋은 “field base”로 지정된 “노드”성분내에 저장된다.
SAVE-REGISTER(operand, Node, field)는 지정된 “피연산자”의 레지스터 수를 템플리트 패턴에 의해 정합된 지정된 “노드”의 지정된 “field”내에 저장한다. 레지스터 수의 이 세트는 어떤 레지스터도 할당되지 않았음을 코드화하는 것을 포함한다. 지정된 피연산자가 메모리 위치에 할당되는 경우 에러가 발생한다.
[코드 방출 동작(Code Emitting Actions)]
MOVE-VALUE(opr-src, opr-dst)는 “opr-src” 피연산자에서 “opr _dst” 피연산자로 값을 이동시키는 코드를 발생시킨다. opr-src 및 opr-dst가 일치하는 경우 발생되는 코드는 없으며 이 동작은 상기의 둘을 일치시키기 위한 할당자로의 힌트이다.
EMIT(opcode, aperand1, operand2…)는 지정된 “opcode”로 구성되고 또한 명령의 어드레스 모드로서 지정된 피연산자 변수들을 사용하는 목적 명령 (object instrucon)을 출력한다.
MAKE _ADDRESS_MODE(opr-offset, opr-base, opr-index, opr-result)는 변수 “opr-result”에서 새로운 피연산자를 만든다. 이것은 VAX 어드레스 모드를 창출하기 위해서 “opr_Offset”를 오프셋으로, “opr base” 베이스 레지스터로, 그리고 “opr_index”를 인덱스 레지스터로 사용하는 VAX 지정 동작이다. “opr_offset”이 빠져 있으면 제로로 추정한다. “opr_offset”이 메모리 위치를 지정하면 “opr_base”는 빠져야만 한다. “opr_base”가 메모리 위치를 지정하는 경우 “opr_offset”은 제로를 지정해야만 하고, “opr_index” 빠져야만 한다.
LOAD-CONSTANT(number, operand)는 지정된 리터럴 “number”를 나타내는 “피연산자”에서 새로운 어드레스 모드를 만든다. “number”는 리터럴 값이지 패턴에 의해 정합된 노드가 아님을 주의 바란다. LITREF ILG 노드의 값을 포함하는 어드레스 모드를 창출하기 위해 LOAD_LITERAL을 대신에 사용한다.
[예]
여기에 매우 단순한 추가 템플리트 및 매우 복잡한 어드레스 템플리트를 포함하는 여러 예가 있다. 이것들은 템플리트를 기입함에 있어 쉽거나 어려운 양쪽 예를 제공해야 한다.
템플리트의 결과값 모드와 및 패턴 정합 잎(leaf)들의 값 모드 세트는 타겟 구조의 데이타 타입 특성을 사용한다. 이들 값 모드는 값이 코드화될 수 있는 상이한 방법들을 열거한 것이다. 다양한 방법으로 수식값을 명명하는 이 열거는 가상 머신에 의해 코드화될 수 있다.
[VAX에 대한 예]
RV(레지스터 값)
MV(간접 및 인덱싱이 없는 메모리 값)
MVIND(간접이지만 인덱싱은 없는 메모리 값)
MV1(바이트 문맥을 갖는 메모리 값)
MV2(워드 문맥을 갖는 메모리 값)
MV4(긴 문맥을 갖는 메모리 값)
MV8(4개의 문맥을 갖는 메모리 값)
MV16(8개의 문맥을 갖는 메모리 값)
AM(간접 및 인덱싱이 없는 어드레스 모드)
AMIND(간접이지만 인덱싱은 없는 어드레스 모드)
AMINX1(바이트 인덱싱을 갖는 어드레스 모드)
AMINX2(워드 인덱싱을 갖는 어드레스 모드)
AMINX4(긴 인덱싱을 갖는 어드레스 모드)
AMINX8(4개의 인덱싱을 갖는 어드레스 모드)
AMINX16(8개의 인덱싱을 갖는 어드레스 모드)
PCFLOW(거짓 라벨 또는 참 라벨로 점프함으로써 나타낸 흐름 부울)
STRINGV(길이 및 메모리 어드레스로서 코드화된 스트링 값)
VARYV(길이 워드의 어드레스로서 코드화된 가변 스트링 값)
VOID(측면-효과만을 갖는 오퍼레이션상에서 사용된 값은 없다 )
[VAX 상에서 단순 ADDL3]
결과값 모드 : RV
패턴 트리 :
0 : ADD, INT32 1,2
1 : LEAF{RV, MV, MVIND, MV4}
2 : LEAF{RV, MV, MVIND, MV4}
비용 : 2
동작 :
Actions(result ; leafl, leaf2) ;
! “result” is the result temporary
! “leaf1” is LEAF 1 : (좌측 피연산자)
! “leaf2” is LEAF 2 : (우측 피연산자)
Undelay(1, leaf1) ;
Undelay(2, leaf2) ;
Use(leaf1) ;
Use(leaf2) ;
Increment_LON ;
Allocate_Permanent(result) ;
Save_TN(result, O, ILG TN) ;
Emit(ADDL3, leaf1, leaf2, result) ;
Delay :
Exit ;
End_Actions ;
주 : 상기 레지스터 할당자에서 사용된 체험적 해법(heuristics)은 결과 피연산자가 피연산자 1 또는 2중의 하나와 일치하게 할당될 높은 가능성을 보증한다. 상기와 같은 할당(Allocation)은 ADDL3 대신에 ADDL2 명령으로 귀결될 것이다.
[VAX상에서의 단순 SUBL3]
결과값 모드 : RV
패턴 트리 :
0 : SUB, INT32 1,2
1 : LEAF{RV, MV, MVIND, MV4}
2 : LEAF{RV, MV, MVIND, MV4}
패턴 테스트 :
없음
비용 : 2
동작 :
Actions(result ; leaf1, leaf2) ;
! “result” is the result temporary
! “leaf1” is LEAF 1 : (좌측 피연산자)
! “leaf2” is LEAF 2 : (우측 피연산자)
Undelay(1, leaf1) ;
Undelay(2, leaf2) ;
Use(leaf2) ;
Increment_LON ;
Use(leaf1) ;
Allocate_Permanent(result) ;
Save_TN(result, O, ILG TN) ;
Emit(SUBL3, leaf2, leaf1, result) ;
Delay ;
Exit ;
End_Action ;
주 : 피연산자 2를 사용한 후이지만 피연산자 1을 사용하기 전에 LON을 증분시키는 것은 레지스터 할당자의 체험적 해법이 피연산자 1과 결과 피연산자 제공할 가능성을 증가시키며, 그 동일한 할당은 SUBL3 대신 SUBL2 명령에 이르게 된다.
[VAX상에서의 바이트 인덱스된 어드레스 모드]
이 템플리트는 가산을 행하도록 k(base-reg)[index-reg] 어드레스 모드를 발생시킨다. 템플리트는 VAX FORTRAN 규칙을 따르며, 이 규칙내에서 이러한 템플리트를 선택함으로써 레지스터가 두개의 피연산자를 유지하는데 사용될 것이 보증된다.
[결과값 모드 : AMINX1]
패턴 트리 :
0 : ADD, INT32 1,2
1 : LITREF, INT32
2 : ADD, INT32 3,4
3 : LEAF{RV}
4 : LEAF{RV}
패턴 테스트 :
NO_OVERFLOW(0) ;
NO_OVERFLOW(2) ;
비용 : 1
동작 :
Action(result ; index_reg, base_reg, leaf4, leaf3, lit) ;
! “result”is result address mode lit(base_reg)[index_reg]
! “index_reg”는 인덱스 스크래치(scratch) 레지스터이다.
! “base_reg”는 베이스 스크래치 레지스터이다.
! “leaf4”는 LEAF 4 : (인덱스 잎)
! “leaf3”는 LEAF 3 : (베이스 잎)
! “lit”는 LITREF 1이다 :
Delay ;
! Force LEAF 4 : into a register
!
Undelay(4, leaf4) ;
Allocate_Delayed(index_reg) ;
Force_Register(index_reg)
Must_Allocate(index_reg) ;
Preference(leaf4, index_reg) ;
Save_Register(index_reg, 0, ILG_Index_Reg) ;
Move_Value(leaf4, index_reg) ;
Use(leaf4) ;
! Force LEAF 3 : into a register
!
Undelay(3, leaf3) ;
Allocate_Delayed(base_reg) ;
Force_Register(base_reg) ;
Must_Allocate(base-reg) ;
Preference(leaf3, base_reg) ;
Save_Register(base_reg, 0, ILG_Base_Reg) ;
Move_Value(leaf3, base_reg) ;
Use(leaf3) ;
! 어드레스 모드 “lit(leaf3)[leaf4]”를 발생
!
Load_Literal(1,lit) ;
Make_Address_Mode(lit, base_reg, Index_reg, result) ;
Increment_LON ;
EXIT ;
End_Actions ;
주 : 레지스터로 LEAF를 강제하는 7동작은 아마 VAX의 공통 오퍼레이션이다.
결과적으로 “macro” 동작은 이들 7동작들들 결합하는 효과를 가진다.
[PRISM 개정판 0.0상에서의 가산을 위한 MOVA의 사용]
결과값 모드 : RV
패턴 트리 :
0 : ADD, INT64 1,2
1 : LITREF, INT64
2 : LEAF{RV}
패턴 테스트 :
Lit_14_Bit(1) ; !리터럴이 14bits에 적합한 경우 계속
비용 : 1
동작 :
Action(result ; leaf2, reg2, reg_result, lit) ;
! “result”는 result temporary
! “leaf2”는 Leaf2를 설명
! “reg2”는 Leaf2를 유지하기 위한 스크래치 레지스터
! “reg_result”는 결과 계산용 스크래치 레지스터
! “lit”는 Literal 1 :
Undelay(2, leaf2) ;
Allocate_Local(reg2) ;
Force_Register(reg2) ;
Must_Allocate(reg2) ;
Save_Register(reg2,0,ILG_reg_0) ;
Move_Value(leaf2, reg2) ;
Use(leaf2) ;
Use(reg2) ;
Allocate_Local(reg_result) ;
Force_Register(reg_result) ;
Must_Allocate(reg_result) ;
Save_Register(reg_result,0,ILG_reg_temp) ;
Use(reg_result) ;
Increment_LON ;
Allocate_Local(result) ;
Save_TN(result,0,ILG_TN) ;
Load_literal(1,lit) ;
Emit(MOVA_Move_Format,lit,reg2,reg_result) ;
Move_Value(reg_result,result) ;
Delay ;
Exit ;
End_Action ;
주 : 레지스터 할당자의 체험작 해법은 leaf2 및 reg2가 동일한 레지스터를 취할 수 있는 높은 가능성을 갖는 것을 보증한다. 또한 result 및 reg_result도 동일 레지스터를 취할 가능성이 매우 높다.
[VAX상에서의 긴 문맥 인덱싱]
이 템플리트는 가산이 뒤따르는 4로 승산을 행하도록 k(leaf3)[leaf6] 어드레스 모드를 생성한다. 템플리트는 VAX PASCAL규칙에 따르며, 여기에서 이러한 템플리트를 선택함으로써 레지스터가 두개의 피연산자를 유지하는데 이용가능하리란 것이 보증되지 않는다. 레지스터가 이용가능치 않다면, 어드레스 모드는 임시 메모리를 사용해 시뮬레이트(simulate)된다.
결과값 모드 : AMINX4
패턴 트리 :
0 : ADD, INT32 1,2
1 : LITREF<INT32
2 : ADD, INT32 3,4
3 : LEAF{RV}
4 : MUL, INT32 5,6
5 : LIT, INT32
6 : LEAF{RV}
패턴 테스트 :
NO_OVERFLOW(0) ;
NO_OVERFLOW(2) ;
NO_OVERFLOW(4) ;
LITERAL_4(5) ; ! 리터럴 값이 4인 경우 계속
비용 : 1
동작 :
Action(result ; index_reg, base_reg, leaf6, leaf3, lit, temp) ;
! “result”는 결과 어드레스 모드
! “index_reg”는 인덱스 스크래치 레지스터
! “base_reg”는 베이스 스크래치 레지스터
! “leaf6” LEAF 6 : (index leaf)
! “leaf3”는 LEAF 3 : (base leaf)
! “lit” is LITREF 1 :
! “temp”is literal #2(No_Index case)
! or is (leaf3)[index_reg]
! (index_Has_Reg_Temp case)
Delay ;
Load_Literal(1,lit) ;
Undelay(6, leaf6)
Undelay(3, leaf3) ;
Allocate_Delayed(index_reg) ;
Increment_Cost(3, index_reg) ;
Preference(leaf6, index_reg) ;
Allocate_Delayed(base reg) ;
Preference(leaf3, base_reg) ;
Increment_LON ;
Test_Memory(index_reg, No_Index) ;
Move_Value(leaf6, index_reg) ;! 레지스터내 인덱스 확인
Test_Memory(base_reg, No_Base) ;
Move_Value(leaf3, base_reg) ; ! 레지스터내 베이스 확인
Make_Address_Mode(lit, base_reg,index_rer,result) ;
! lit5(base2)[index 1]
Exit ;0
Label(No_Index) ; ! 레지스터 인덱스 temp 없음
Load_Constant(2, temp) :
Emit(ASHL, temp, leaf6, index_reg) ; !ASHL #2, leaf6, index_mem
Emit(ADDL2, leaf3, index_reg) ; !ADDL2 leaf3, index_mem
Emit(ADDL2, lit, index_reg) ; !ADDL2 #lit, index_mem
Make-Addres≤_Mode(index_reg, result) ; !@index_mem
Exit ;
Label(No_Base) ; ! 레지스터 베이스 temp없음
Test_Memory(leaf3, Index_Has_Reg_temp) ;
! 인덱스가 temp내에 있지 않다.
Emit(ADDL3, lit, leaf3, base_reg) ; ! ADD2 #lit, leaf3, base_mem
Make-Address_Mode(base_reg, index_reg, result) ;
! ⓐbase_mem(index_reg)
Label(Index_Has_Reg_Temp) ; ! No base reg but index in temp
Make_Address_Mode(leaf3, index_reg, temp) ;
Emit(MOVAL, temp, index_reg) ;! MOVALⓐleaf3[index_reg], index_reg
Emit(ADDL2,lit,index_reg) ; ! ADDL2 #lit, index_reg
Make_Address_Mode(index_reg, result) ; ! (index_reg)
EXIT ;
End_Actions ;
[부록]
[기본 타입의 정의 ]
다음의 루우틴은 GEM IL에 의해 정의된 표시 타입에 대응하는 기본 타입을 정의한다. GEM-TD-DEF-Basic-TYPE은 영(nil), 어드레스, 부호있는 및 부호없는 정수, 부동 및 복소수 타입들을 정의한다. GEM-TD-DEF-CHAR-TYPE은 문자의 정의가 기본 타입의 수를 넘어서 정의될 수 있게 한다.
부울이 기본 타입으로 고려되지 않음을 주위하라. Pascal과 같은 언어용 컴파일러가 부울을 참 및 거짓요소를 포함하는 목록으로서 정의하는 것이 제안된다.
TYPE_NODE=
GEM_TD_DEF_BASIC_TYPE(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
BASIC_TYPE : value)는
기본 타입을 정수나 실수로서 정의한다. DECL_BLK는 그 타입이 정의되는 블럭노드이다. LOCATOR는 GEM 또는 외래 위치지정자이며, LOCATOR(위치지정자)는 널(null ; 공집합의)위치 지정자일 수 있다.
TYPE_NAME은 타입을 설명하는 가변 스트링이며, 널일 수 있다. BASIC_TYPE은 정의되고 있는 타입이며, GEM_TYP 목록이 요소이어야 한다. 특히, BOOL, BITS, STR8 및 STR16 GEM-TYP 요소들은 제외된다.
TYPE_NODE=
GEM_TD_DEF_CHAR_TYPE(
DECL_BLK: in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
BASIC_TYPE : value)는
문자를 기본 타입으로서 정의한다. 예로 문자는 UINT8, INT8, UINT16, UINT32, 등일 수 있다. DECL-BLK는 그 타입이 정의되는 블럭 노드이다. LOCATOR는 GEM 또는 외래 위치지정자이며, 널 위치지정자일 수 있다. TYPE-NAME은 타입을 설명하는 가변 스트링이며, 널 상태일 수 있다. BASIC-TYPE은 정의되는 타입이며, 문자 세트의 표현과 크기를 결정한다. 이것은 GEM-TYP 목록의 요소여야만 하며 크기 8, 16 및 32비트의 부호있는 및 부호없는 정수로 제한된다.
[문자 및 스트링 군의 정의]
GEM-TD-DEF-STRING 및 GEM-TO-DEF-BITSTRING은 주어진 베이스 타입의 문자 및 비트군을 정의한다.
TYPE_NODE=
GEM_TD_DEF_STRING(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR:value,
TYPE_NAME : in VS_STR.
STRING_TYPE : value,
CHAR_TYPE : value,
STRING_LB : in GEM_NODE,
STRING_UB : in GEM_NODE)는
STRING-TYPE의 문자 스트링을 정의한다. 스트링의 요소들은 CHAR-TYPE에 의해 정의된 타입의 문자이며 그리고 상기 스트링은 하위 및 상위 피연산자, STRING_LB를 가진다. 스트링 크기(요소들의 수)는 STRING_UB-STRING_LB+1이다. 미지 크기의 문자 STRING_LB 값보다 작은 스트링 STRING_UB값에 의해 나타내어진다.
DECL_BLK는 그 타입의 정의된 블럭 노드이다. LOCATOR은 GEM이나 외래 위치지정자이며, 널 위치지정일 수도 있다. TYPE_NAME은 상기 타입을 설명하는 가변 스트링으로 널(정보의 부재) 상태일 수도 있다. STRING-TYPE은 스트링 표시로 목록 GEM_STRING REPR의 멤버로 되는 것처럼 정의된다. CHAR-TYPE은 호출에 의해 GEM-TD-DEF-CHAR-TYPE으로 복귀된 스트링 문자 타입에 대해 발생된 타입 노드로의 핸들(handle)이며, 널 상태일 수도 있다. STRING_UB 및 STRING_LB는 스트링의 상위 및 하위 바운드이다.
TYPE_NODE=
GEM_TD_DEF_BITSTRING(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
BITSTRING_LB : in GEM_LITERAL_NODE,
BITSTRING_UB : in GEM_LITERAL_NODE)는
BITSTRING-UB-BITSTRING-LB+1 요소로 구성되는 비트 스트링을 정의한다. 미지 크기의 비트 스트링은 BITSTRING_LB 값보다 작은 BITSTRING-UB 값에 의해 표시된다.
DECL_BLK는 그 타입의 정의된 블럭 노드이다. LOCATOR는 GEM 또는 외래 위치지정자로, 널 상태의 위치지정자일 수 있다. TYPE_NAME은 상기 타입을 설명하는 가변 스트링으로 널 상태일 수도 있다. BITSTRING_UB 및 BITSTRING_LB는 비트 스트링의 상위 및 하위 바운드이다.
[Typedefs 및 포인터의 정의]
GEM-TD-DEF-TYPEDEF는 기존 타입에 대한 새로운 명칭 또는 동의어를 정의한다. GEM_TD_SET_POINTER_TYPE는 타입화 또는 비타입화된 포인터를 정의한다. 포인터와 관련된 상기 타입이 GEM 타입 정의 서비스로 지정된 그 타입 정보를 가진후 GEM-TD-SET-POINTER_TYPE은 이전에 지정된 포인터의 타입을 설정한다.
TYPE_NODE=
GEM_TD_DEF_TYPEDEF(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
DEF_TYPE : value)
는 새로운 타입명을 정의하며 그것을 타입 노드 DEF-TYPE에 의해 표현된 타입과 연관시킨다. DECL-BLK는 그 타입의 정의된 블럭 노드이다. LOCATOR는 GEM 또는 외래 위치지정자이며, 널 상태의 위치지정자일 수도 있다. TYPE-NAME는 상기 타입을 설명하는 가변 스트링으로 널 상태일 수도 있다. DEF-TYPE은 기존 타입 정의용으로 창출된 타입 노드이다.
TYPE_NODE=
GEM_TD_DEF_POINTER(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
POINTER_TYPE: value)
는 포인터 타입을 정의한다. POINTER-TYPE은 기존 타입 정의에 대한 타입 노드일 수도 있고, 또는 타입화되지 않은 포인터를 나타내는 널 상태일 수도 있다. TYPE-NAME은 타입을 설명하는 가변 스트링으로 널 상태일수도 있다. LOCATOR는 GEM 또는 외래 위치지정자로, 널 상태의 위치지정자 일수도 있다.
DECL-BLK는 그 타입이 정의되는 블럭 노드이다.
TYPE_NODE=
GEM_TD_SET_POINTER_TYPE(
POINTER_TYPE : value,
NEW_TYPE : value)
는 호출에 의해 GEM-TD-DEF-POINTER로 창출된 기존 포인터 정의에 대해, 포인터와 연관된 타입을 재정의한다. POINTER-TYPE은 포인터용으로 정의된 기존 타입 노드에 대한 핸들이다. NEW-TYPE는 기존 타입 정의에 대해 창출된 타입 노드에 대한 핸들이다
[범위, 목록 및 세트의 정의]
GEM-TD-DEF-RANGE, GEM-TD-DEF-ENUM, GEM-TD-ENUM-ELEMENT 및 GEM-TD-DEF-SET는 정의된 타입상에서 범위, 목록, 목록 요소 및 세트들을 정의한다.
TYPE_NODE=
GEM_TD_DEF_RANGE(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
RANGE_TYPE : value,
RANGE_LOW_VAL : in GEM_LITERAL_NODE,
RANGE_HIGH_VAL : in GEM_LITERAL_NODE)
는 범위 타입을 정의한다. 이 범위는 기초적 타입, RANGE_TYPE, 및 리터럴 노드 RANGE-LOW-VAL 및 RANGE-HIGH-VAL에 의해 나타내지듯이 범위의 하위 및 고위값으로 정의된다. DECL-BLK는 그 타입이 정의되는 블럭 노드이다. LOCATOR은 GEM 또는 외래 위치지정자이며, 널 상태의 위치지정자일 수도 있다. TYPE_NAME은 타입을 설명하는 가변 스트링이며 널 상태일 수도 있다. RANGE_TYPE은 기존 기본 타입 정의의 타입 로드로의 핸들이다. RANGE-LOW-VAL 및 RANGE-HIGH-VAL은 범위내에서 하위 및 고위값을 나타내는 리터럴 노드에 대한 포인터이다.
TYPE_NODE=
GEM_TD_DEF_ENUM(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
ENUM_TYPE : value)
는 목록을 정의한다. 이 목록의 요소들은 루우틴 GME_TD_ENUM_ELEMENT로의 호출에 의해 정의된다. DECL_BLK는 그 타입이 정의되는 블록 노드이다. LOCATOR는 GEM 또는 외래 위치지정자이며, 널 위치지정자일 수 있다. ENUM_TYPE은 기존 베이직 타입 정의용으로 창출된 타입 노드에 대한 핸들이다. 전단(front-end)는 처음부터 마지막 오더에서 목록 요소들을 목록 정의에 적용해야만 한다.
TYPE_NODE=
GEM_TD_SET_ENUM_ELEMENT(
ENUM_TYPE : value,
LOCATOR : value,
ENUM_ELEMENT_NAME : in VS_STR,
ENUM_ELEMENT_VALUE : in GEM_LITERAL_NODE)는
타입 노드 핸들 ENUM-TYPE으로 지시된 목록에 대해서, 값 ENUM-ELEMENT_VALUE를 갖는 ENUM-ELEMENT-NAME으로 명명된 요소를 정의한다. ENUM-TYPE은 목록에 대한 기존 타입 노드에 대한 핸들이다. LOCATOR는 GEM 또는 외래 위치지정자이며, 널 상태의 위치지정자일 수도 있다. ENUM-ELEMENT-NAME은 목록 요소를 정의하는 가변 스트링이다. ENUM-ELEMENT-VALUE은 요소값을 정의하는 리터럴 노드이다.
TYPE_NODE=
GEM_TD_DEF_SET(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
SET_TYPE : value)
는 타입 노드 핸들 SET_TYPE에 의해 정의된 타입 세트를 정의한다. DECL BLK는 그 타입이 정의되는 블럭 노드이다. LOCATOR는 GME 또는 외래 위치지정자이며, 널 상태의 위치지정자일 수도 있다. TYPE_NAME은 타입을 설명하는 가변 스트링으로 널 상태일 수도 있다. SET-TYPE은
○ GEM_TD_DEF_BASIC_TYPE
○ GEM_TD_DEF_CHAR_TYPE
○ GEM_TD_DEF_ENUM
○ GEM_TD_DEF_RANGE
○ GEM_TD_TYPEDEF
에 의해 복귀되어진 핸들일 수도 있다.
[Array의 정의]
루우틴 GEM-TD-DEF-ARRAY 및 GEM-TD-SET-ARRAY-BOUNDS는 어레이와 어레이 차원(dimension)의 한계를 정의하기 위해 사용될 수 있다. 어레이 차원의 바운드는 고정적이거나, 조절가능하게, 또는 추정적으로 정의될 수 있다.
TYPE_NODE=
GEM_TD_DEF_ARRAY(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
ARRAY_ELEMENT_TYPE : value,
ARRAY_DIM_COUNT : value)
는 타입 ARRAY_ELEMENT_TYPE의 어레이를 정의한다. DECL_BLK는 그 타입이 선언되는 블럭 노드이다. LOCATOR는 GEM 또는 외래 위치지정자이며, 널 상태의 위치지정자 일수도 있다. TYPE-NAME은 타입을 설명하는 가변 스트링으로 널 상태일 수도 있다. ARRAY-ELEMENT-TYPE은 어레이 요소에 타입을 정의하는 타입 노드에 대한 핸들이다. ARRAY-DIM-COUNT는 어레이 대한 차원의 수이다.
차원 카운트는 리터럴 노드라기보다 값처럼 전달된다는 것을 알아야 한다. 어레이 차원의 바운드는 GEM-TD-SET-ARRAY-BOUNDS 루우틴으로써 지정된다.
TYPE_NODE=
GEM_TD_SET_ARRAY_BOUNDS(
ARRAY_TYPE : value,
LOCATOR : value,
ARRAY_DIM : value,
DIM_LOW_BONND : in GEM_NODE,
DIM_HIGH_BOUND : in GEM_NODE,
DIM_INDEX_TYPE : value,
DIM_STRIDE in GEM_LITERAL_NODE)
는 핸들 ARRAY-TYPE에 의해 지정된, 어레이 타입 정의에 대해서, ARRAY-DIM에 의해 지시된 차원의 바운드를 세트시킨다. LOCATOR는 GEM 또는 외래 위치지정자로서, 널 상태의 위치 지정자일 수도 있다. DIM-INDEX-LOW 및 DIM-INDEX-HIGH는 차원의 하위 바운드 및 상위 바운드를 정의한다. DIM-INDEX-TYPE은 어레이 차원을 인덱싱하기 위해 사용된 타입을 정의하는 타입 노드에 대한 핸들이다. DIM-STRIDE는, 정의되는 차원의 연속적 요소들간의 바이트에서, 그 크기를 정의한다. 블랭크(blank) A상수 상위 또는 하위 바운드는 리터럴 노드에 의해 지정된다. 비 상수 바운드는 값들의 위치를 정의하는 심볼 노드에 의해 표시된다.
[구조(변수 및 합집합)의 정의]
다음의 루우틴은 변수와 합집합을 포함하여 구조를 정의하는데 사용된다. 구조는 하기의 루우틴을 호출함으로써 정의되며, 변수 성분들을 가질 수 있다.
○ GEM_TD_DEF_STRUCT
○ GEM_TD_DEF-STRUCT_ELEMENT
○ GEM_TD_DEF_STRUCT_SELECTOR
○ GEM_TD_DEF_STRUCT_VARIANT
GEM_TD_SET_SELECTOR RANGE
○ GEM_TD_SET_SELECTOR_DEFAULT
○ GEM_TD_DET_UNION
○ GEM_TD_SET_UNION_MEMBER
TYPE_NODE=
GEM_TD_DEF_STRUCT(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
STRUCTURE_SIZE : value)
는 구조 또는 레코드(record)를 정의한다. DECL-BLK는 그 구조가 선언되는 블럭 노드이다. LOCATOR는 GEM 또는 외래 위치지정자이며, 널 상태의 위치지정자일 수도 있다. TYPE-NAME은 타입을 설명하는 가변 스트링으로 널 상태일 수도 있다. STRUCTURE-SIZE는 바이트에서의 구조의 크기이다.
TYPE_NODE=
GEM_TD_SET_STRUCT_ELEMENT(
STRUCT_TYPE : value,
VARIANT_PARENT : value,
LOCATOR : value,
ELEMENT_NAME : in VS_STR,
ELEMENT_TYPE : value,
ELEMENT_LOC_BYTE : in GEM_LITERAL_NODE,
ELEMENT_LOC_BIT : in GEM_LITERAL_NODE,
ELEMENT_SIZE : in GEM_LITERAL_NODE)
는 구조 정의 핸들 STRUCT-TYPE에 의해 정의된 구조의 요소를 정의한다. 상기 요소는 ELEMENT-NAME으로 명명되고 그리고 타입 노드 핸들 ELEMENT-TYPE에 의해 정의된 타입을 갖는다. VARIANT_PARENT는 요소의 직접적인 부모변수(parent variant)이거나, 만약 요소가 변수의 구성요소를 정의하지 않으면 널 상태이다. LOCATOR는 GEM 또는 외래 위치지정자로 널 상태의 위치지정자일 수도 있다. 그 위치는 정의되는 구조의 루트(root)에 비례하며, ELEMENT-LOC-BYTE 및 ELEMENT-LOC-BIT로 지정된다.
구조 요소의 크기는 ELEMENT_SIZE에 의해 비트로 지정된다. ELEMENT-SIZE는 다음의 C 프로그램 부분에서의 구조 요소들 C1 및 C2의 정의를 뒷받침하기 위해 지정된다.
typedef strcut m1{
char c1 : 4 ;
char c2 : 4 ;
};
TYPE_NODE=
GEM_TD_DEF_STRUCT_SELECTOR(
STRUCT_TYPE : value,
VARIANT_PARENTR : value,
LOCATOR : value,
ELEMENT_NAME : in VS_STR,
ELEMENT_TYPE : value,
ELEMENT_LOC_BYTE : in GEM_LITERAL_NODE,
ELEMENT_LOC_BIT : in GEM_LITERAL_NODE,
ELEMENT_SIZE : in GEM_LITERAL_NODE)
는 레코드의 변수 성분에 대한 선택를 정의한다. 선택자는 구조의 변수를 결정하는 구조 요소이다. 선택자 요소는 ELEMENT-NAME으로 명명되고 그리고 타입 노드 핸들 ELEMENT-TYPE에 의해 정의된 타입을 갖는다. VARIANT_PARENT는 선택자 요소의 직접적인 부모 변수이거나, 또는 요소가 변수의 구성 요소가 아니면 널 상태이다. LOCATOR는 GEM 또는 외래 위치지정자이며, 널 상태의 위치지정자일 수도 있다. 그 위치는 정의되는 구조의 루트에 비례하며, ELEMENT-LOC-BYTE 및 ELEMENT-LOC-BIT에 의해 지정된다. 구조 요소의 크기는 ELEMENT-SIZE에 의해 비트로 지정된다.
TYPE_NODE=
GEM_TD_DEF_STRUCT_VARIANT(
SELECTOR_TYPE : value,
LOCATOR : value)는
구조의 변수를 정의한다. SELECTOR-TYPE은 변수를 선택하는 타입 노드이다. LOCATOR는 GEM 또는 외래 위치지정자로, 널 상태의 위치지정자일 수도 있다. 변수를 선택하는 상기 선택자의 값들은 GEM-TD-SET-SELECTOR-RANGE 및 GEM-TD-SET-SELECTOR-DEFAULT 루우틴에 의해 지정된다.
TYPE_NODE=
GEM_TD_SET_SELECTOR_RANGE(
VARIANT_TYPE : value,
LOCATOR : value,
RANGE_LOWER_BOUND : in GEM_LITERAL_NODE,
RANGE_UPPER_BOUND : in GEM_LITERAL_NODE)
는 변수 VARIANT-TYPE에 대한 선택자 범위를 정의한다. LOCATOR는 GEM이나 외래 위치지정자이며 널 상태의 위치지정자일 수도 있다. 단일 선택자 값을 정의할때, RANGE-UPPER-BONND는 RANGE-LOWER-BOUND와 동일한 값을 가져야만 한다. 단일 선택자들과 범위 선택자들의 조합은 변수에 적용될 수 있다.
TYPE_NODE=
GEM_TD_SET_SELECTOR_DEFAULT(
VARIANT_TYPE : value,
LOCATOR : value)
는 선택자의 모든 값들이 열거되어지지 않았을때, 변수 타입 VARIANT_TYPE가 생략성(default) 변수가 되는 것으로 정의한다. LOCATOR는 GEM 또는 외래 위치지정자이며 널 상태의 위치지정자일수도 있다. 스칼라 선택자 값을 정의할때, RANGE-UPPER-BOUND는 RANGE-LOWER-BOUND와 동일한 값을 가져야만 한다. 스칼라 및 범위 선택자들의 조합은 변수에 적용될 수도 있다.
TYPE_NODE=
GEM_TD_DEF_UNION(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
UNION_SIZE : in GEM_LITERAL_NODE)
는 합집합을 정의한다. DECL-BLK는 그 구조가 선언되는 블럭 노드이다. TYPE-NAME은 타입을 설명하는 가변 스트링이며, 널 상태일 수도 있다. LOCATOR는 GEM 또는 외래 위치지정자로, 널 상태의 위치지정자일 수도 있다. UNION-SIZE는 바이트에서의 구조 크기이며, 합집합의 구성요소는 루우틴 GEM-TD-SET-UNION-MEMBER로 호출에 의해 정의된다.
TYPE_NODE=
GEM_TD_SEF_UNION_MEMBER(
UNION_TYPE : value,
LOCATOR : value,
MEMBER_NAME : in VS_STR,
MEMBER_TYPE : value)
는 타입 노드 UNION-TYPE으로 나타낸 합집합의 구성요소를 정의한다. UNION-TYPE은 상기 구성요소를 포함하는 합집합의 타입 노드이다. LOCATOR는 GEM 또는 외래 위치지정자이며 널 상태의 위치지정자일 수도 있다. MEMBER-NAME은 구성요소의 이름을 정의하는 가변 스트링이며, MEMBER-TYPE은 정의되는 구성요소의 타입 노드이다.
[기능 및 루우틴 파라미터의 정의]
TYPE_NODE=
GEM_TD_DEF_FUNCTION_TYPE(
DECL_BLK : in_out GEM_BLOCK_NODE,
LOCATOR : value,
TYPE_NAME : in VS_STR,
FUNCTION_TYPE : value)
는 절차 파라미터의 타입을 타입 노드 FUNCTION-TYPE에 의해 지정된 타입처럼 정의된다. 이것은 엔트리 심볼의 정의하는데 사용된다기 보다는 파라미터를 루우틴에게 설명하는 것임을 주의하라, DECL-BLK는 그 타입이 정의되는 블럭 노드이다. LOCATOR는 GEM 또는 외래 위치지정자로 널 상태의 위치지정자일 수도 있다. TYPE _NAME은 상기 타입을 설명하는 가변 스트링으로 널 상태일 수도 있다.
[예]
하기의 예들은 많은 타입과 심볼들 및, 그것들을 GEM에 설명하는데 사용되는 메카니즘들을 설명한다. 파스칼 타입 부울은 GEM 타입 unit32를 넘어서는 목록으로 정의되는 점을 숙지하기 바란다.
[기본 타입들의 예]
main( ){
int a ;
unsigned int ua :
float x :
double xx :
char str { } =MHello, world\nM;
:
TYPINT32=GEM_TD_DEF_BASIC_TYPE(main block, locator, 'int', GEM_TYP_K_ INT32)
TYPUINT32=GEM_TD_DEF_BASIC_TYPE(main_block, locator, 'unsigned int', GE M_TYP_K_UINT32) ;
TYPREALF=GEM_TD_DEF_BASIC_TYPE(main_block, locator, 'float', GEM_TYP_ K_REALF) ;
TYPREALG=GEM_TD_DEF_BASIC_TYPE(main_block, locator, 'double', GEM_TY P_K_REALG) ;
TYPCHAR8=GEM_TD_DEF_BASIC_TYPE(main_block, locator, 'char', GEM_TYP _K_INT8) ;
TYPSTRING=GEM_TD_DEF_STRING(main_block, locator, 'string', GEM_STRREP _K_ASCIZ, TYPCHAR8, litnode(len(str))) ;
[부울 타입의 정의에 대한 예]
procedure bt ;
boolean myflag ;
TYPUINT32=GEM_TD_DEF_BASIC_TYPE(bt_block, locator, 'unsigned int' GEM_TYP_UNIT32) ;
TYPBOOL=GEM_TD_DEF_ENUM_(bt_block, locator, 'boolean', TYPUNIT32) ;
GEM_TD_SET_ENUM_ELEMENT(TYPBOOL, locaotor, 'false' litnode(val=0)) ;
GEM_TD_SET_ENUM_ELEMENT(TYPBOOL, locaotor, 'true' litnode(val=1)) ;
[문자 및 비트군의 예]
routine testit(parml,…)=
begin
own status : bitvetor[15],
flagbits : bitvector[8] ;
bind dbits=parml : bitvector[ ] ;
:
end ;
TYPBITS1=GEM_TD_DEF_BITSTRING(testit_block, locator, 'bitvector' litnode(val=0), litnode(val=14)) ;
TYPBITS2=GEM_TD_DEF_BITSTRING(testit_block, locator, 'bitvector' litnode(val=0), litnode(val=7)) ;
TYPBITS3=GEM_TD_DEF_BITSTRING(testit_block, locator, 'bitvector' litnode(val=0), litnode(val=1)) ;
[포인터 및 타입 정의의 예]
int echo( ) {
sttrcut tnode {
}
typedef struct tnode ssval ;
tnode *tp ;
znode *zp ;
struct znodes {
}
TYPSTRUCT1=definition of structure tnode
; ssval을 tnode에 대한 가명으로 정의
TYPALIAS=GEM_TD_DEF_TYPEDEF(echo_block,locator, 'ssval', TYPSTRUCT1)
TYPPTR1=GEM_TD_DEF_POINTER(echo_block, locator, null, TYPSTRUCT1)
; “가명” 포인터를 정의한 후, 구조 znode를 정의. 최종적으로 포인터 타입 수정
TYPPTR2=GEM_TD_DEF_POINTER(echo_block, locator, 'pointer', null) ;
TYPSTRUCT2=definition of structure znode
GEM_TD_DEF_POINTER_TYPE(TYPPTR2, TYPSTRUCT2) ;
[범위 목록 및 세트의 예]
void myproc( ) {
type
dn1=0..6 ;
dn2=100..105 ;
dn3=66000..66001 ;
weekday=(mon, tue, wed, thu, fri) ;
t_typ=(int, re, boo) ;
var
s1 : set of dnl ;
s2 : set of weekday ;
s3 : set of t_trp ;
! 범위 dn1을 정의
TYPUINT8=GEM_TD_DEF_BASIC_TYPE(myproc_block, locator, null, GEM_TYP _K_UNIT8) ;
TYPRANGE1=GEM_TD_DEF_RANGE_(myproc_block, locator, 'dn1', TYPUINT8, litnode (val=0), litnode(val=6)) ;
! 범위 dn2를 정의
TYPRANGE2=GEM_TD_DEF_RANGE_(myproc_block, locator, 'dn2', TYPUINT8, litnode(val=100), litnode(val=105));
! 범위 dn3를 정의
TYPINT32=GEM_TD_DEF_BASIC_TYPE(myproc_block, locator, null, GEM_TYP_ K_UNIT32) ;
TYPRANGE=GEM_TD_DEF_RANGE(myproc_block, TYPINT32, 'dn3' litnode(val= 66000), litnode (val=66001)) ;
TYPENUM=GEM_TD_DEF_ENUM(myproc_block, locator, 'weekday', TYPUNIT 8) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM1,locator, 'mon', litnode(va=0)) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM1,locator, 'tue', litnode(val=1)) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM1,locator,'wed', litnode(val=2)) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM1, locator, 'thu', litnode(val=3)) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM1, locator, 'fri', litnode(val=4)) ;
TYPENUM2=GEM_TD_DEF_ENUM(myproc_block, locator, 't_typ', TYPUINT32) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM2, locator, 'int', litnode(val=0)) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM2, locator, 're', litnode(val=1)) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM2, locator, 'boo', litnode(val=2)) ;
!vars s1, s2 및 s3에 대한 세트를 정의
TYPSET1=GEM_TD_DEF_SET(myproc_block, locator, 'set', TYPRANGE1) ;
TYPSET2=GEM_TD_DEF_SET(myproc_block, locator, 'set', TYPENUM) ;
TYPSET3=GEM_TD_DEF_SET(myproc_block, locator, 'set', TYPENUM) ;
[어레이의 예]
procedure dimmer ;
type
nd=record…
var
ary1 : array[1..10] of integer ;
ary2 : array[1..10,100..110] of integer ;
ary3 : array[900..1700] of nd ;
ary4 : array['a'..'z'] of nd ;
TYPSTRUCT1=Definition of record type nd.
! 어레이 'ary1'을 정의
TYPINT32=GEM_TD_DEF_BASIC_TYPE(dimmer_block, locator, null, GEM_TYP_K_INT32) ;
TYPARRAY=GEM_TD_DEF_ARRAY(dimmer_block, locator, null, TYPINT32, 1) ; litnode(val=1), litnode(val=10), TYPINT32, litnode(value=4)) ;
! 어레이 'ary2'를 정의
TYPARRY=GEM_TD_DEF_ARRAY(dimmer_block, locator, null, TYPINT32, 2) ;
GEM_TD_SET_ARRAY_BOUNDS(TYPARRAY, locator, 1, litnode(val=1), litnode(val=10), TYPINT32, litnode(value=4) ;
GEM_TD_SET_ARRAY_BOUNDS(TYPARRAY, locator, 2, litnode(val=100), litnode(val=110), TYPINT32, litnode(value=40) ;
! 또 다르게는 ary2에 대한 어레이 사양은 하기와 같이 정의될 수 있다.
TYPARRAY1=GEM_TD_DEF_ARRAY(dimmer, block, locator, null, TYPINT32, 1) ;
GEM_TD_SET-ARRAT_BOUNDS(TYPARRAY1, lacotor, 1, litnode(val=100), litnode(val=110), TYPINT32, litnode(value=4)) ;
TYPARRAY2=GEM_TD_DEF_ARRAY(dimmer_block, locaotor, null, TYPARRAY1, 1) ;
GEM_TD_SET-ARRAT_BOUNDS(TYPARRAY2, lacotor, 1, litnode(val=1), litnode(val=10), TYPINT32, litnode(value=40)) ;
! 어레이 'ary3'를 정의
TYPARRAY=GEM_TD_DEF_ARRAY(dimmer_block, locator,null, TYPSTRUCT1, 1) ;
GEM_TD_SET-ARRAY_BOUNDS(TYPARRAY, locator, 1, litnode(val=900), litnode(val=1700), TYPINT32, sizeof(nd)) ;
! 어레이 'ary4'를 정의
TYPCHAR=GEM_TD_DEF_CHAR_TYPE(dimmer_block, locator, null, GEM_TYP_UNIT8) ;
TYPARRAY=GEM_TD_DEF_ARRAY(dimmer_block, locator, TYPSTRUCT1, 1) ;
GEM_TD_SET_ARRAY_BOUNDS(TYPARRAY, locator, 1, litnode(val=97), litnode(val=122)) ; litnode(val=900), litnode(val=1700), TYPINT32, sizeof(nd) ;
[조절 가능한 어레이에 대한 정의의 예]
subroutine x(cv, ary1, ary2, a, b)
character*(*)cv
dimension ary1(1 : 10, 1 : b)
dimension ary2(a : b, 1 : *)
TYPINT32=GEM_TD_DEF_BASIO_TYPE(x_block,locator,null,GEM_TYP_K_INT32) ;
TYPCHAR=GEM_TD_DEF_CHAR-TYPE(x_block,locator,null,GEM_TYP_K_INT8) ;
! 어레이 'cv'를 정의
TYPARRAY=GEM_TD_DEF_ARRAY(x_block, locator, null, TYPCHAR, 1) ;
GEM_TD_SET-ARRAY_BOUNDS(TYPARRAY, locator, 1, litnode(val=1), litnode(val=1), TYPINT32, litnode(val=1) ;
! 어레이 'ary1'를 정의
TYPARRAY=GEM_TD_DEF_BASIC_TYPE(x_block,locator,null,GEM_TYP_K_REASF) ;
TYREALF=GEM_TD_DEF_ARRAY(x_block, locator, TYPREALF, 2) ; 2, litnode (val=4)) ;
GEM_TD_SET_ARRAY_BOUNDS(TYPARRAY, 1, locator, litnode(val=1), litnode(val=10), TYPINT32 litnode(value=4)) ;
GEM_TD_SET_ARRAY_BOUNDS(TYPARRAY, 2, locator, litnode(val=1), b_symbol, TYPINT32 , litnode(value=4)) ; ********
! 어레이 'ary2'를 정의
TYPARRAY=GEM_TD_DEF_ARRAY(x_block,locator,null, TYPREALF, TYPINT32, 2, litnode(val =4)) ;
GEM_TD_SET_ARRAY_BOUNDS(TYPARRAY, locator, 1, asymbol, b_symbol, TYPINT32, litnodei(val=4)) ;
GEM_TD-SET-ARRAY_BOUNDS(TYPARRAY, locator, 2, litnode(val=1), litnode(val=1), TYPINT32, litnode(value=4)) ;
[구조 및 변수의 예]
type
t_trp=(it, re, ptr, v1, v2, v3) ;
ndp=end ;
nd=record
nxt : ndp ;
case it : t_typ of
tt : (iv : integer):
re : (rv : real) ;
ptr : (pr : ndp ; sum : integer) ;
otherwise :(il : integer ; 12 : real) ;
end ;
! 예로 사용된 기본 타입들을 정의
TYPIN32=GEM_TD_DEF_BASIC_TYPE(typeit_block,locator,'integer',GEM_TYP_K_INT32) ;
TYPREALF=GEM_TD_DEF_BASIC_TYPE(typeit_block,locator,'real',GEM_TYP_K_REALF) ;
TYPNIL=GEM_TD_DEF_BASIC_TYPE(typeit_block,locator,null,GEM_TYP_K_NIL) ;
! ndp 포인터를 nd로 정의
TYPPTR=GEM_TD_DEF_POINTER(typeit_block, locator, 'ndp' TYPNIL) ;
! t-trp 목록을 정의
TYPENUM_GEM_TD_DEF_ENUM(myproc_node. ; locator, 't_typ', TYPINT32) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM, locator, 'it', litnode(val=0) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM, locator, 're', litnode(val=1) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM, locator, 'boo', litnode(val=2) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM, locator, 'v1', litnode(val=3) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM, locator, 'v2', litnode(val=4) ;
GEM_TD_SET_ENUM_ELEMENT(TYPENUM, locator, 'v3', litnode(val=5) ;
! 구조 정의 nd를 정의
TYPSTRUCT=GEM_TD_DEF_STRUCT(typeit_block, locator, 'nd', litnode(nd_size)) ;
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, null, locator, 'nxt', TYPPTR, litnode(1_byte(nxt)), litnode(1_bite(nxt))), linode(bit_size(nxt))) ;
! 변수 부분에 대한 선택자를 정의
TYPSEL=GEM_TD_DEF_STRUCT_SELECTOR(TYPSTRUCT, null 'tt', TYPENUM, litnode(1_byte (tt)), litnode(1_bit(tt), litnode(bit_size(tt))) ;
! 디폴트(default)를 포함하는 구조 변수들을 정의
V1=GEM_TD_DEF_STRUCT_VARIANT1(TYPSEL, locator) ;
GEM_TD_SET_SELECTOR_RANGE(V1,locator,litnode(val=0),
litnode(val=0))
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, V1, locaotor, 'iv', TYPINT, litnode(1_byte (iv)), litnode(1_bit(iv)), litnode(bit_size (iv))
V2=GEM_TD_DEF_STRUCT_VARIANT(TYPSEL, locator) ;
GEM_TD_SET_SELECTOR_RANGE(V2, locator, litnode(val=1), litnode(val=1))
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, V2, locator, 'rv', TYPREALF, litnode(1_byte(rv)), litnode(1_bit(rv)), litnode(bit_size (rv))
V3=GEM_TD_DEF_STRUCT_VARIANT(TYPSEL, locaotor) ;
GEM_TD_SET_SELECTOR_RANGE(V3, locaotor, litnode(val=2), litnode(val=2))
GEM_TD_SEF_STRUCT_ELEMENT(TYPSTRUCT, V3, locator, 'pv', TYPPTR, litnode(1_byte (pv)), litnode(1_bit(pv)), litnode(bit_size(pv))
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, V3, locator, 'sum', TYPPTR, litnode(1_byte (sum)), litnode(1_bit(sum)), litnode(bit_size(sum))
V4=GEM_TD_DEF_STRUCT_VARIANT(TYPSEL, locator) ;
GEM_TD_SET_SELECTOR_RANGE(V4, locator) ;
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, V4, locator, 'il', TYPINT, litnode(1_byte(i1)), litnode(1_bit(il)),litnode(bit_size(i1))
GEM_TD_SEF_STRUCT_ELEMENT(TYPSTRUCT, V4, locaotor, 'i2', TYPINT, litnode(1_byte(i2)), litnode(1_bit(i2)), litnode(bit_size(i2))
GEM_TD_SET_POINTER_TYPE(TYPPTR, TYPSTRUCT) ;
[구조 및 합집합 정의의 예]
main( ){
struct dim3{
int x ;
int y ;
int z ;
}:
union anon{
int ival ;
float fval ;
char *pval ;
struct dim3 loc ;
} :
struct n1{
union anon a ;
union anon b :
union anon c ;
} ;
struct nl, nl1, nl2, nl3 ;
TYPINT32=GEM_TD_DEF_BASIC_TYPE(main_block,locator,'int', GEM_TYP_K_INT32) ;
TYPREALF=GEM_TD_DEF_BASIC_TYPE(main_block,locaotor,null, GEM_TYP_K_INT32) ;
TYPCHAR=GEM_TD_DEF_CHAR_TYPE(main_block,locator,null, GEM_TYP_K_UNIT8) ;
TYPPTR=GEM_TD_DEF_POINTER(main_block, locator, null, TYPCHAR) ;
! 구조 'dim3'를 정의
TYPSTRUCT=GEM_TD_DEF_STRUCT(main_block,locator,'dim3', litnode(dim3_size)) ;
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, mull, locator, 'x', TYPINT32, loc_byte(x), loc_bit(x), litnode(x_size)) ;
GEM_TD_SET_STRUCT_ELEMENT(TYPSTYRUCT, null, locator, 'y', TYPINT32, loc_byte(y), loc_bit(y), litnode(y_size)) ;
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, null, locaotor, 'z',TYPINT32, loc_byte(z), loc_bit(z), litnode(z_size)) ;
! 합집 'anon'을 정의
TYPUNION=GEM_TD_DEF_UNION(main_block,locator,'anon, litnode(anon_size)) ;
GEM_TD_SET_UNION_MEMBER(TYPUNION, locaotor, 'ival', TYPINT32) ;
GEM_TD_SET_UNION_MEMBER(TYPUNION, locaotor, 'fval', TYPREALF) ;
GEM_TD_SET_UNION_MEMBER(TYPUNION, locaotor, 'pval', TYPPTR) ;
GEM_TD_SET_UNION_MEMBER(TYPUNION, locaotor, 'loc', TYPSTRUCT) ;
! 구조 'n1'을 정의
TYPSTRUCT=GEM_TD_DEF_STRUCT(main_block,locator, 'n1', litnode(n1_size)) ;
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, null, locator, 'a', TYPUNION, loc_byte(a), loc_bit(a), litnode(anon_size)) ;
GEM_TD_SET_STRUCT_ELEMENT(TYPSTRUCT, null, locator, 'b', TYPUNION, loc_byte(b), loc_bit(b), litnode(anon_size)) ;
GEM_TD_DEP_STRUCT_ELEMENT(TYPSTRUCT, null, locator, 'c', TYPUNION, loc_byte(c), loc_bit(c), litnode(anon_size)) ;
[기능 파라미터 정의의 예]
function x(function grin : real ; procedure bearit ) : integer
TYPNIL=GEM_TD_DEF_BASIC_TYPE(x_block, locator, 'real' GEM_TYP_K REALF) ;
TYPPREALF=GEM_TD_DEF_BASIC_TYPE(x_block, locator, null GEM_TYP_K NIL) ;
! 기능 파라미터 'grin'에 대한 타입을 정의
TYPROC=GEM_TD_DEF_FUNCTION_TYPE(x_block, locator, 'nulll' TYPNIL) ;
! 절차 파라미터 'bearit'에 대한 타입을 정의
TYPFUNCT=GEM_TD_DEF_FUNTION_TYPE(x_block, locator, null, TYPREALF) ;

Claims (7)

  1. 각종 다른 고급 프로그래밍 언어중 하나로 된 소스 코드를 포함하는 입력 코드 모듈에서 정의된 프로그램을 언어 특정성을 갖는 컴파일러 전단을 사용하여 액세스하는 단계와 ; 상기 컴파일러 전단내의 변환기에 의해 중간 언어로 상기 프로그램을 정의하도록, 각각의 튜플이 상기 입력 코드 모듈의 단일 수식을 표시하는 튜플들로 구성되는 중간 언어 그래프, 및 심볼 테이블을 발생하는 단계와 ; 상기 중간 언어 그래프를 액세스하여 상기 중간 언어 그래프를 재구성함으로써 상기 프로그램을 최적화하는 단계와 ; 각종 다른 타겟 컴퓨터 아키텍쳐중 하나에 대한 코드 발생기에 의해 상기 중간 언어 그래프로부터 목적 코드를 발생하는 단계를 포함하는데, 상기 최적화 단계가 상기 프로그램내의 유도 변수의 수식을 검출하고 그 유도 변수의 수식을 변경된 중간 언어 그래프에 의해 정의된 동등한 수식으로 변환하여, 승산을 가산으로 대체함으로써 상기 프로그램에 대한 상기 튜플로부터 생성된 상기 목적 코드의 실행 시간을 감소시키는 과정을 포함하는 것을 특징으로 하는 코드 번역 방법.
  2. 제1항에 있어서, 상기 중간 언어 그래프가 순서화된 일련의 상기 튜플들을 포함하는 블록들로 구성되는 것을 특징으로 하는 코드 번역 방법.
  3. 제2항에 있어서, 상기 각 블록들이 엔트리 또는 라벨로 시작되어 중간 출구없이 복귀로 끝나며, 상기 튜플들이 연산자, 연산자 데이타 타입 및 피연산자를 표시하는 필드를 갖는 데이타 구조인 것을 특징으로 하는 코드 번역 방법.
  4. 각종 다른 고급 프로그래밍 언어중 하나로 된 소스 코드를 포함하는 입력 코드 모듈에서 정의된 프로그램을 액세스하기 위한 언어 특정성을 갖는 컴파일러 전단과 ; 각각의 튜플이 상기 입력 코드 모듈의 단일수식을 표시하는 튜플들로 구성되는 중간 언어 흐름 그래프를 발생하여 상기 프로그램을 중간 언어로 정의하기 위한 상기 컴파일러 전단내의 변환기와 ; 상기 중간 언어 그래프를 액세스하여 상기 중간 언어 그래프를 재구성함으로써 상기 프로그램을 최적화시키기 위한 최적화 수단과 ; 상기 중간 언어 그래프를 액세스함으로써 각종 다른 타겟 컴퓨터 아키덱쳐중 하나에 대한 목적 코드를 발생하기 위한 코드 발생기를 구비하는데, 상기 최적화 수단이 상기 프로그램의 유도 변수의 수식을 검출하고 그 유도 변수의 수식을 변경된 중간 언어 그래프에 의해 정의된 동등한 수식으로 변환하여, 승산을 가산으로 대체함으로써 상기 프로그램에 대한 상기 튜플로부터 생성된 상기 목적 코드의 실행 시간을 감소시키기 위한 수단을 구비하는 것을 특징으로 하는 코드 번역 장치.
  5. 제4항에 있어서, 상기 튜플들이 연산자, 연산자 데이타 타입 및 피연산자를 표시하는 필드를 갖는 데이타 구조이며, 상기 중간 언어 그래프가 순서화된 일련의 상기 튜플들을 포함하는 블록들로 구성되는데 상기 각 블록들은 입구 또는 라벨로 시작하여 중간 출구없이 복귀로 끝나고, 상기 중간 언어 그래프를 액세스함으로써 상기 코드를 최적화하기 위한 상기 수단이 상기 튜플들의 결과 종속성 표시에 응답하는 것을 특징으로 하는 코드 번역 장치.
  6. 각각의 튜플이 소스 코드 언어의 단일 수식을 표시하는 튜플들로 구성되는 중간 언어 그래프를 언어 특정성을 갖는 컴파일러 전단을 사용하여 중간 언어로 발생하는 단계와 ; 상기 중간 언어 그래프의 유도 변수의 수식을 검출하고 그 유도 변수의 수식을 변경된 중간 언어 그래프에 의해 정의된 동등한 수식으로 변환하여, 승산을 가산으로 대체함으로써 상기 프로그램용의 상기 튜플로부터 생성된 목적 코드의 실행 시간을 감소시키는 단계를 포함하는 것을 특징으로 하는 컴파일러내의 코드 최적화 방법.
  7. 제6항에 있어서, 상기 중간 그래프가 순서화된 일련의 상기 튜플들을 포함하는 블록들로 구성되는 것을 특징으로 하는 컴파일러내의 코드 최적화 방법.
KR1019920702693A 1991-02-27 1992-02-18 다중 언어 최적화 컴파일러의 유도 수식 분석 KR960003138B1 (ko)

Applications Claiming Priority (11)

Application Number Priority Date Filing Date Title
US66272591A 1991-02-27 1991-02-27
US66247791A 1991-02-27 1991-02-27
US66246191A 1991-02-27 1991-02-27
US66246491A 1991-02-27 1991-02-27
US66248391A 1991-02-27 1991-02-27
US662,461 1991-02-27
US662,477 1991-02-27
US662,464 1991-02-27
US662,725 1991-02-27
US662,483 1991-02-27
PCT/US1992/001278 WO1992015942A1 (en) 1991-02-27 1992-02-18 Analyzing inductive expressions in a multilanguage optimizing compiler

Publications (1)

Publication Number Publication Date
KR960003138B1 true KR960003138B1 (ko) 1996-03-05

Family

ID=27542049

Family Applications (5)

Application Number Title Priority Date Filing Date
KR1019920702693A KR960003138B1 (ko) 1991-02-27 1992-02-18 다중 언어 최적화 컴파일러의 유도 수식 분석
KR1019920702694A KR950006609B1 (ko) 1991-02-27 1992-02-18 다중 패스코드 발생에 있어서 템플리트를 이용한 다중 언어 최적화 컴파일러
KR1019920702691A KR950006608B1 (ko) 1991-02-27 1992-02-18 다중 언어 최적화 컴파일러내의 상수 폴딩 메카니즘을 구성하는 방법
KR1019920702692A KR960003050B1 (ko) 1991-02-27 1992-02-18 중간 컴파일러 언어에 대한 심볼 테이블
KR1019920702690A KR950006607B1 (ko) 1991-02-27 1992-02-18 다중 언어 최적화 컴파일러내의 표시 효과용 인터페이스

Family Applications After (4)

Application Number Title Priority Date Filing Date
KR1019920702694A KR950006609B1 (ko) 1991-02-27 1992-02-18 다중 패스코드 발생에 있어서 템플리트를 이용한 다중 언어 최적화 컴파일러
KR1019920702691A KR950006608B1 (ko) 1991-02-27 1992-02-18 다중 언어 최적화 컴파일러내의 상수 폴딩 메카니즘을 구성하는 방법
KR1019920702692A KR960003050B1 (ko) 1991-02-27 1992-02-18 중간 컴파일러 언어에 대한 심볼 테이블
KR1019920702690A KR950006607B1 (ko) 1991-02-27 1992-02-18 다중 언어 최적화 컴파일러내의 표시 효과용 인터페이스

Country Status (9)

Country Link
EP (5) EP0526621A1 (ko)
JP (5) JPH0762826B2 (ko)
KR (5) KR960003138B1 (ko)
AU (5) AU658399B2 (ko)
CA (5) CA2081473C (ko)
DE (1) DE69225281T2 (ko)
FI (2) FI924846A0 (ko)
NO (2) NO924115L (ko)
WO (5) WO1992015942A1 (ko)

Families Citing this family (21)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP2847688B2 (ja) 1993-05-27 1999-01-20 松下電器産業株式会社 プログラム変換装置およびプロセッサ
DE69434971T2 (de) * 1993-05-27 2008-01-17 Matsushita Electric Industrial Co., Ltd., Kadoma Programmumsetzungseinheit
JP2755154B2 (ja) * 1994-02-23 1998-05-20 日本電気株式会社 プログラム変換処理装置およびプログラム変換処理方法
US5740469A (en) * 1995-04-24 1998-04-14 Motorola Inc. Apparatus for dynamically reading/writing multiple object file formats through use of object code readers/writers interfacing with generalized object file format interface and applications programmers' interface
CA2251369A1 (en) * 1998-10-26 2000-04-26 International Business Machines Corporation System and method for analyzing dependencies in a computer program
US7000222B1 (en) 1999-08-19 2006-02-14 International Business Machines Corporation Method, system, and program for accessing variables from an operating system for use by an application program
US7966609B2 (en) 2006-03-30 2011-06-21 Intel Corporation Optimal floating-point expression translation method based on pattern matching
KR101314247B1 (ko) * 2009-09-03 2013-10-02 한국전자통신연구원 위성 관제 시스템에서 위성 관제 운용 자동화를 위한 언어변환장치 및 방법
US20130167144A1 (en) * 2009-09-04 2013-06-27 Bernd Mathiske Virtual Machine Persisted Within Itself
US8832672B2 (en) 2011-01-28 2014-09-09 International Business Machines Corporation Ensuring register availability for dynamic binary optimization
EP2687981B1 (en) * 2012-07-18 2017-12-27 MStar Semiconductor, Inc. Automated compiler specialisation for global optimisation
US20160019037A1 (en) * 2014-07-21 2016-01-21 Xamarin Inc. Managing parameter types for generic functions
US9183020B1 (en) 2014-11-10 2015-11-10 Xamarin Inc. Multi-sized data types for managed code
US9213638B1 (en) 2015-03-24 2015-12-15 Xamarin Inc. Runtime memory management using multiple memory managers
JP6481515B2 (ja) 2015-05-29 2019-03-13 富士通株式会社 情報処理装置、コンパイル方法、及びコンパイラプログラム
WO2018042520A1 (ja) * 2016-08-30 2018-03-08 三菱電機株式会社 プログラム編集装置、プログラム編集方法及びプログラム編集プログラム
CN108108169B (zh) * 2017-12-27 2020-11-03 广东小天才科技有限公司 一种基于Jenkins的多分支的构建方法及系统
JP7015207B2 (ja) * 2018-04-27 2022-02-02 株式会社日立製作所 ビジュアルプログラミングツールを用いてフローを作成することを支援する装置および方法
JP7163697B2 (ja) * 2018-09-28 2022-11-01 富士通株式会社 生成プログラム,情報処理装置及び生成方法
KR102165928B1 (ko) * 2019-12-04 2020-10-14 서울대학교 산학협력단 전자 장치, 전자 장치의 컴파일링 방법 및 전자 장치의 동작 방법
CN116360788A (zh) * 2023-02-17 2023-06-30 深圳市亿维自动化技术有限公司 结构化文本编程语言的编译方法、编译器及电子设备

Family Cites Families (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US4667290A (en) * 1984-09-10 1987-05-19 501 Philon, Inc. Compilers using a universal intermediate language

Also Published As

Publication number Publication date
CA2081449C (en) 1999-04-13
EP0529049A1 (en) 1993-03-03
EP0532731A1 (en) 1993-03-24
NO924114L (no) 1992-12-18
FI924845A0 (fi) 1992-10-26
WO1992015943A1 (en) 1992-09-17
AU1569892A (en) 1992-10-06
AU1429292A (en) 1992-10-06
JPH0769834B2 (ja) 1995-07-31
DE69225281D1 (de) 1998-06-04
FI924846A (fi) 1992-10-26
JPH0769832B2 (ja) 1995-07-31
CA2081473C (en) 1999-04-06
DE69225281T2 (de) 1999-01-07
NO924115D0 (no) 1992-10-23
JPH0769833B2 (ja) 1995-07-31
JPH06501579A (ja) 1994-02-17
AU663311B2 (en) 1995-10-05
JPH06501582A (ja) 1994-02-17
WO1992015941A1 (en) 1992-09-17
JPH06501583A (ja) 1994-02-17
AU653799B2 (en) 1994-10-13
AU663493B2 (en) 1995-10-12
AU1439792A (en) 1992-10-06
WO1992015942A1 (en) 1992-09-17
CA2081477A1 (en) 1992-08-28
AU1420492A (en) 1992-10-06
NO924115L (no) 1992-12-18
CA2081475C (en) 1998-05-05
CA2081473A1 (en) 1992-08-28
CA2081476A1 (en) 1992-08-28
FI924846A0 (fi) 1992-10-26
CA2081475A1 (en) 1992-08-28
WO1992015945A1 (en) 1992-09-17
KR950006608B1 (ko) 1995-06-19
EP0526622A1 (en) 1993-02-10
KR950006607B1 (ko) 1995-06-19
JPH0762825B2 (ja) 1995-07-05
CA2081449A1 (en) 1992-08-28
KR960003050B1 (ko) 1996-03-04
WO1992015944A1 (en) 1992-09-17
KR950006609B1 (ko) 1995-06-19
JPH06501581A (ja) 1994-02-17
EP0528008A1 (en) 1993-02-24
AU663310B2 (en) 1995-10-05
FI924845A (fi) 1992-10-26
EP0529049B1 (en) 1998-04-29
AU1442292A (en) 1992-10-06
JPH06501580A (ja) 1994-02-17
NO924114D0 (no) 1992-10-23
EP0526621A1 (en) 1993-02-10
JPH0762826B2 (ja) 1995-07-05
CA2081477C (en) 1992-08-28
AU658399B2 (en) 1995-04-13

Similar Documents

Publication Publication Date Title
US5613117A (en) Optimizing compiler using templates corresponding to portions of an intermediate language graph to determine an order of evaluation and to allocate lifetimes to temporary names for variables
US5577253A (en) Analyzing inductive expressions in a multilanguage optimizing compiler
KR960003138B1 (ko) 다중 언어 최적화 컴파일러의 유도 수식 분석
US5659753A (en) Interface for symbol table construction in a multilanguage optimizing compiler
US5836014A (en) Method of constructing a constant-folding mechanism in a multilanguage optimizing compiler
US5493675A (en) Compiler back end calling predetermined front end routines that use effect and dependency indicators to provide information to the compiler to determine the validity of an optimization
Sah et al. A new architecture for the implementation of scripting languages
IL100988A (en) A method for compiling a cipher
Àµ½ ½Á et al. ¹® º» ¼º» µ «5® ³½ «eµ²½µf¶¥¥ § «5º» º¿ ¾

Legal Events

Date Code Title Description
A201 Request for examination
E902 Notification of reason for refusal
G160 Decision to publish patent application
E701 Decision to grant or registration of patent right
GRNT Written decision to grant
FPAY Annual fee payment

Payment date: 19990303

Year of fee payment: 4

LAPS Lapse due to unpaid annual fee