컴파일러

Compiler

컴퓨팅에서 컴파일러는 하나의 프로그래밍 언어(소스 언어)로 쓰여진 컴퓨터 코드를 다른 언어(대상 언어)로 번역하는 컴퓨터 프로그램이다. "컴파일러"라는 이름은 주로 실행 가능한 프로그램을 만들기 위해 상위 레벨 프로그래밍 언어에서 하위 레벨 언어(예: 어셈블리 언어, 객체 코드 또는 머신 코드)로 소스 코드를 변환하는 프로그램에 사용된다.[1][2]: p1

다른 유용한 형태로 생산되는 컴파일러에는 여러 가지 종류가 있다. 크로스 컴파일러는 크로스 컴파일러 자체가 실행되는 것과 다른 CPU나 운영 체제에 대한 코드를 생성한다. 부트스트랩 컴파일러는 컴파일하려는 언어로 작성된다. 낮은 수준의 언어에서 높은 수준의 언어로 번역하는 프로그램이 디컴파일러다. 고수준의 언어를 번역하는 프로그램을 보통 소스 대 소스 컴파일러 또는 트랜스필러라고 부른다. 언어 리라이터는 보통 언어의 변화 없이 표현의 형태를 번역하는 프로그램이다. 컴파일러 컴파일러는 컴파일러(또는 컴파일러의 일부)를 생산하는 컴파일러다.

컴파일러는 종종 사전 처리, 어휘 분석, 파싱, 의미 분석(syntax-direct translation), 중간 표현으로의 입력 프로그램 전환, 코드 최적화코드 생성이라고 불리는 다음과 같은 작업의 일부 또는 전부를 수행할 가능성이 있다. 컴파일러는 일반적으로 이러한 단계를 모듈형 구성요소로 구현하여 대상 출력에 대한 소스 입력의 변환의 효율적 설계와 정확성을 촉진한다. 잘못된 컴파일러 동작으로 인한 프로그램 결함은 추적하고 작업하기가 매우 어려울 수 있으므로 컴파일러 구현자는 컴파일러의 정확성을 보장하기 위해 상당한 노력을 기울인다.[3]

컴파일러만이 소스 프로그램을 변환하는 데 사용되는 언어 프로세서가 아니다. 통역사는 지시된 작업을 변환한 다음 실행하는 컴퓨터 소프트웨어다.[2]: p2 번역과정은 컴퓨터 언어의 설계에 영향을 미쳐 컴파일이나 해석의 선호로 이어진다. 이론적으로, 프로그래밍 언어는 컴파일러와 통역자를 둘 다 가질 수 있다. 실제로 프로그래밍 언어는 단 한 가지(컴파일러 또는 통역자)와 연관되는 경향이 있다.

역사

일반적인 다국어 다중 대상 컴파일러의 작동 다이어그램

과학자, 수학자, 공학자들이 개발한 이론 컴퓨팅 개념은 제2차 세계 대전 동안 디지털 현대 컴퓨팅 발전의 기초를 형성했다. 원시 바이너리 언어는 디지털 장치가 기본 기계 아키텍처의 0과 0과 회로 패턴만을 이해하기 때문에 진화했다. 1940년대 후반, 컴퓨터 아키텍처의 보다 실행 가능한 추상화를 제공하기 위해 어셈블리 언어가 만들어졌다. 초기 컴퓨터의 메모리 용량이 제한되어 최초의 컴파일러를 설계할 때 상당한 기술적 난제로 이어졌다. 따라서 편성 과정은 여러 개의 작은 프로그램으로 나눌 필요가 있었다. 프런트 엔드 프로그램은 대상 코드를 생성하기 위해 백엔드 프로그램이 사용하는 분석 제품을 생산한다. 컴퓨터 기술이 더 많은 자원을 제공했기 때문에 컴파일러 설계는 컴파일 프로세스에 더 잘 맞출 수 있다.

프로그래머가 높은 수준의 언어를 사용하는 것이 보통 더 생산적이기 때문에, 디지털 컴퓨터가 제공하는 능력으로부터 자연스럽게 높은 수준의 언어의 개발이 뒤따른다. 고수준 언어는 고수준 언어 구조를 형성하는 구문과 의미에 의해 엄격히 정의되는 형식 언어다. 이러한 공식 언어의 요소에는 다음이 포함된다.

  • 알파벳, 모든 유한한 기호 집합
  • 문자열, 기호의 유한 시퀀스
  • 언어, 알파벳에 있는 모든 문자열.

언어의 문장은 문법이라 불리는 일련의 규칙으로 정의될 수 있다.[4]

백커스-나우르 양식(BNF)은 언어의 "센스" 구문을 설명하고 있으며, 존 백커스에 의해 알골 60의 구문에 사용되었다.[5] 이 아이디어들은 언어학자 노암 촘스키의 문맥 없는 문법 개념에서 유래한다.[6] BNF와 그 확장은 프로그래밍 공지의 구문을 기술하는 표준 도구가 되었고, 많은 경우 컴파일러의 부분은 BNF 기술에서 자동으로 생성된다.[7]

1940년대에 콘라드 주세플랑카쿨(Plan Miculus)이라는 알고리즘 프로그래밍 언어를 설계했다. 1970년대까지는 실제 구현이 이루어지지 않았지만, 이후 1950년대 후반 켄 아이버슨이 설계한 APL에서 볼 수 있는 개념을 제시했다.[8] APL은 수학 계산을 위한 언어다.

디지털 컴퓨팅이 형성되는 기간 동안의 고급 언어 설계는 다양한 애플리케이션을 위한 유용한 프로그래밍 도구를 제공했다.

  • 공학 및 과학 응용을 위한 FORTRAN(Formula Translation)은 최초의 고급 언어로 간주된다.[9]
  • COBOL(Common Business-Oriented Language)은 A-0FLOW-MATIC에서 발전하여 비즈니스 애플리케이션의 지배적인 고급 언어가 되었다.[10]
  • 심볼 연산용 LISP(List Processor)[11]

컴파일러 기술은 고수준 소스 프로그램을 디지털 컴퓨터의 저수준 표적 프로그램으로 엄격히 정의해야 하는 필요성에서 발전했다. 컴파일러는 소스 코드의 분석을 처리하기 위한 프런트 엔드, 분석을 대상 코드로 통합하기 위한 백 엔드로 볼 수 있다. 프런트 엔드 및 백 엔드 사이의 최적화는 보다 효율적인 대상 코드를 생성할 수 있다.[12]

컴파일러 기술 개발의 초기 단계:

  • 1952년: 앨릭 글레니가 맨체스터 대학의 맨체스터 마크 1 컴퓨터를 위해 개발한 오토코드 컴파일러는 일부 사람들에 의해 최초의 컴파일된 프로그래밍 언어라고 여겨진다.
  • 1952: 레밍턴 랜드그레이스 호퍼 팀은 A-0 프로그래밍 언어에 대한 컴파일러(그리고 이를 설명하기 위해 컴파일러라는 용어를 만들었다)[13][14]를 작성했는데, A-0 컴파일러는 풀 컴파일러의 현대적 개념보다는 로더나 링크커로 더 기능했다.
  • 1954–1957: IBM의 존 백커스(John Backus)가 이끄는 팀이 FORTRAN을 개발했는데, 이는 보통 최초의 고급 언어로 여겨진다. 1957년에 그들은 FORTRAN 컴파일러를 완성했는데, 일반적으로는 모호하지 않게 완성된 컴파일러를 최초로 도입한 것으로 인정받고 있다.
  • 1959: CODASYL(데이터 시스템 언어에 관한 회의)은 COBOL의 개발을 시작했다. COBOL 설계는 A-0과 Flow-MATIC에 적용되었다. 1960년대 초까지 COBOL은 여러 아키텍처에 대해 편집되었다.
  • 1958–1962: MIT의 존 매카시LISP를 설계했다.[15] 기호 처리 능력은 인공지능 연구에 유용한 기능을 제공했다. 1962년 LISP 1.5 릴리즈에서는 스테판 러셀이 쓴 통역사와 팀 하트와 마이크 레빈이 쓴 컴파일러 겸 조립자 다니엘 J. 에드워즈가 쓴 통역기가 몇 가지 도구에 주목했다.[16]

초기 운영 체제와 소프트웨어는 조립 언어로 작성되었다. 1960년대와 1970년대 초에는, 시스템 프로그래밍을 위한 고급 언어의 사용은 여전히 자원 한계로 인해 논란이 되었다. 그러나, 몇 가지 연구와 업계의 노력은 BCPL, BLISS, B, C와 같은 높은 수준의 시스템 프로그래밍 언어로의 전환을 시작했다.

1966년 캠브리지 대학의 마틴 리차드가 설계한 BCPL(Basic Composed Programming Language)은 원래 컴파일러 필기 도구로 개발되었다.[17] 리차드의 책은 언어와 그 컴파일러에 대한 통찰력을 제공한다.[18] BCPL은 여전히 연구에[19] 사용되는 영향력 있는 시스템 프로그래밍 언어일 뿐만 아니라 B 언어와 C 언어의 설계에 대한 기초를 제공했다.

BLISS(시스템 소프트웨어 구현을 위한 기본 언어)는 W.A.에 의해 DEC(Digital Equipment Corporation) PDP-10 컴퓨터를 위해 개발되었다. 울프의 카네기 멜론 대학(CMU) 연구팀. CMU 팀은 1년 후인 1970년에 BLISS-11 컴파일러를 개발하기 시작했다.

시간 공유 운영 체제 프로젝트인 멀티크스(Multixed Information and Computing Service)는 MIT, Bell Labs, General Electric(Layer Honeywell)이 참여했으며 MIT의 페르난도 코르바토(Fernando Corbato)가 주도했다.[20]멀틱스는 IBM과 IBM User Group이 개발한 PL/I 언어로 작성되었다.[21] IBM의 목표는 비즈니스, 과학 및 시스템 프로그래밍 요구사항을 충족하는 것이었습니다. 고려할 수 있었던 다른 언어가 있었지만 PL/I는 실행되지 않았음에도 불구하고 가장 완벽한 솔루션을 제공했다.[22] Multics 프로젝트의 첫 몇 년 동안, 언어의 하위 집합은 Bell Labs의 Doug McIlory와 Bob Morris에 의해 Early PL/I (EPL) 컴파일러로 조합된 언어로 컴파일될 수 있었다.[23] EPL은 완전한 PL/I를 위한 부트스트래핑 컴파일러가 개발될 때까지 프로젝트를 지원했다.[24]

벨 랩스는 1969년 "시간이 지나면서 그룹 노력이 처음에는 경제적으로 유용한 시스템을 만들어내지 못하면서 희망은 좌절감으로 대체되었다"[25]고 멀티크스 프로젝트를 떠났다. 지속적인 참여는 프로젝트 지원 비용을 증가시킬 것이다. 그래서 연구원들은 다른 개발 노력에 눈을 돌렸다. BCPL 개념에 기초한 시스템 프로그래밍 언어 B데니스 리치와 켄 톰슨이 썼다. Ritchie는 B를 위한 부트스트래핑 컴파일러를 만들고, B에 PDP-7을 위한 유니크(Uniplexed Information and Computing Service) 운영 체제를 작성했다. 유니크스는 결국 Unix라는 철자가 되었다.

Bell Labs는 B와 BCPL을 기반으로 C의 개발과 확장을 시작했다. BCPL 컴파일러는 Bell Labs에 의해 Multics로 운송되었고 Bell Labs에서는 BCPL이 선호되는 언어였다.[26] 처음에는 C 컴파일러가 개발되는 동안 Bell Labs의 B 컴파일러의 프런트 엔드 프로그램이 사용되었다. 1971년, 새로운 PDP-11은 B에 대한 확장을 정의하고 컴파일러를 다시 작성할 수 있는 자원을 제공했다. 1973년까지 C 언어의 디자인은 본질적으로 완성되었고 PDP-11을 위한 Unix 커널은 C로 다시 작성되었다. 스티브 존슨은 새로운 기계에 대한 C 컴파일러의 리타깃을 지원하기 위해 PCC(Portable C Compiler) 개발을 시작했다.[27][28]

객체 지향 프로그래밍(OOP)은 애플리케이션 개발과 유지보수를 위한 몇 가지 흥미로운 가능성을 제공했다. OOP 개념은 더 거슬러 올라가지만 LISPSimula 언어 과학의 일부였다.[29] Bell Labs에서는 C++의 개발이 OOP에 관심을 갖게 되었다.[30] C++는 1980년에 시스템 프로그래밍에 처음 사용되었다. 초기 설계는 시물라 개념으로 C언어 시스템 프로그래밍 기능을 활용했다. 1983년에 객체 지향 시설이 추가되었다.[31] Cfront 프로그램은 C84 언어 컴파일러를 위한 C++ 프런트엔드를 구현했다. 그 후 몇 년 동안 C++의 인기가 높아지면서 C++ 컴파일러가 개발되었다.

많은 애플리케이션 도메인에서, 더 높은 수준의 언어를 사용하는 아이디어는 빠르게 인기를 끌었다. 새로운 프로그래밍 언어에 의해 지원되는 기능성의 확대와 컴퓨터 아키텍처의 복잡성 증가 때문에 컴파일러는 더욱 복잡해졌다.

국방고등연구계획국(DARPA, Defense Advanced Research Projects Agency)은 1970년 울프의 CMU 연구팀과 함께 컴파일러 프로젝트를 후원했다. 생산 품질 컴파일러-컴파일러 PQCC 설계는 소스 언어와 타겟에 대한 공식 정의에서 생산 품질 컴파일러(PQC)를 생성한다.[32] PQCC는 파서 발전기(예: Yacc)로서의 전통적인 의미를 넘어 컴파일러-컴파일러라는 용어를 크게 성공하지 못하고 확장하려고 했다. PQCC를 컴파일러 제너레이터라고 하는 것이 더 적절할 수 있다.

코드 생성 프로세스에 대한 PQCC 연구는 진정한 자동 컴파일러 쓰기 시스템을 구축하고자 했다. 그 노력은 PQC의 위상 구조를 발견하고 설계했다. BLISS-11 컴파일러는 초기 구조를 제공했다.[33] 단계에는 분석(프론트 엔드), 가상 머신에 대한 중간 변환(중간 엔드) 및 대상에 대한 변환(백 엔드)이 포함되었다. TCOL은 PQCC 연구를 위해 중간 표현에서 언어별 구조를 다루기 위해 개발되었다.[34] TCOL의 변화는 다양한 언어를 지원했다. PQCC 프로젝트는 자동 컴파일러 구조 기법을 조사했다. 설계 개념은 객체 지향 프로그래밍 언어인 Ada의 컴파일러와 컴파일러를 최적화하는 데 유용하다는 것이 입증되었다.

Ada Stoneman 문서는 커널(KAPSE) 및 미니멀(MAPSE)과 함께 프로그램 지원 환경(APSE)을 공식화했다. 에이다님 통역관 NYU/ED는 미국 국가표준연구소(ANSI)와 국제표준기구(ISO)의 개발 및 표준화 노력을 지원했다. 미국 군대의 초기 Ada 컴파일러 개발은 Stoneman Document의 라인을 따라 완전한 통합 설계 환경에 컴파일러를 포함했다. 육군과 해군은 DEC/VAX 아키텍처를 목표로 하는 ALS(Ada Language System) 프로젝트를, 공군은 IBM 370 시리즈를 대상으로 하는 AIE(Ada Integrated Environment)에 착수했다. 이 프로젝트들은 원하는 결과를 제공하지 못했지만, 에이다님의 개발에 대한 전반적인 노력에 기여했다.[35]

다른 에이다 컴파일러의 노력은 요크 대학교의 영국, 칼스루에 대학교의 독일에서 진행되었다. 미국에선 베르딕스(Rational이 인수한 later)가 '베르딕스 아다 개발 시스템(VADS)'을 육군에 전달했다. VADS는 컴파일러를 포함한 일련의 개발 툴을 제공했다. Unix/VADS는 육군 CECOM 평가에서 Motorola 68020을 대상으로 한 DEC Ultrix 및 Sun 3/60 Solaris와 같은 다양한 Unix 플랫폼에서 호스팅될 수 있었다.[36] 곧 에이다 유효성 검사 테스트를 통과한 많은 에이다 컴파일러들이 출시되었다. 자유 소프트웨어 재단 GNU 프로젝트는 다국어와 대상을 지원하는 핵심 기능을 제공하는 GNU 컴파일러 컬렉션(GCC)을 개발했다. 에이다 버전 GNAT는 가장 널리 사용되는 에이다 컴파일러 중 하나이다. GNAT는 무료지만 상업적 지원도 있다. 예를 들어, AdaCore는 Ada에게 상업적 소프트웨어 솔루션을 제공하기 위해 1994년에 설립되었다. GNAT Pro는 GNU GCC 기반 GNAT와 통합 개발 환경을 제공하는 툴 제품군을 포함한다.

높은 수준의 언어가 컴파일러 연구 개발을 계속 추진했다. 초점 영역에는 최적화 및 자동 코드 생성이 포함되었다. 프로그래밍 언어와 개발 환경의 동향은 컴파일러 기술에 영향을 미쳤다. 더 많은 컴파일러들이 언어 배포(PERL, Java Development Kit)와 IDE의 구성요소(VADS, Eclipse, Ada Pro)에 포함되었다. 기술의 상호관계와 상호의존성이 커졌다. 웹 서비스의 등장은 웹 언어와 스크립팅 언어의 성장을 촉진했다. 스크립트는 사용자가 시스템에서 실행할 명령을 입력할 수 있는 CLI(Command Line Interface)의 초기 시대로 거슬러 올라간다. 셸 프로그램을 작성하기 위해 언어와 함께 개발된 사용자 셸 개념. 초기 윈도 디자인은 간단한 일괄 프로그래밍 기능을 제공했다. 이러한 언어의 전통적인 변형에는 통역이 사용되었다. 널리 쓰이지 않는 반면, Bash와 Batch 컴파일러는 쓰여졌다. 보다 최근에 정교하게 해석된 언어는 개발자 도구 키트의 일부가 되었다. 현대의 스크립트 언어로는 PHP, Python, Ruby, Lua 등이 있다. (Lua는 게임 개발에서 널리 사용된다.) 이 모든 것들은 통역사와 컴파일러 지원을 가지고 있다.[37]

"50년대 후반 컴파일 분야가 시작되었을 때, 그것의 초점은 높은 수준의 언어 프로그램을 기계 코드로 변환하는 것에 한정되었다... 컴파일러 분야는 컴퓨터 아키텍처, 프로그래밍 언어, 형식적 방법, 소프트웨어 엔지니어링, 컴퓨터 보안 등 다른 분야와 점점 더 얽혀가고 있다.[38] "Compiler Research: 향후 50년" 기사는 객체 지향 언어와 자바의 중요성에 주목했다. 향후 연구 대상으로는 보안과 병렬 컴퓨팅이 꼽혔다.

컴파일러 구조

컴파일러는 고수준의 소스 프로그램에서 저수준의 대상 프로그램으로 형식적인 변환을 구현한다. 컴파일러 설계는 엔드투엔드 솔루션을 정의하거나 프리프로세서, 조립자, 링크 등과 같은 다른 컴파일 도구와 인터페이스하는 정의된 서브셋을 다룰 수 있다. 설계 요건은 컴파일러 구성요소 간 내부 및 지원 도구 세트 간 외부적으로 엄격하게 정의된 인터페이스를 포함한다.

초기에는 컴파일러 설계에 대해 취해진 접근방식은 처리할 컴퓨터 언어의 복잡성, 설계자의 경험, 가용 자원의 영향을 직접적으로 받았다. 자원 한계로 인해 소스코드를 두 번 이상 통과해야 했다.

한 사람이 쓴 비교적 간단한 언어에 대한 컴파일러는 단일의 단일 소프트웨어일 수 있다. 그러나 소스 언어가 복잡해지면서 설계는 여러 상호의존적 단계로 분할될 수 있다. 별도의 단계는 컴파일 프로세스의 기능에 개발을 집중시키는 설계 개선사항을 제공한다.

원패스 대 멀티패스 컴파일러

컴파일러를 패스 수별로 분류하는 것은 컴퓨터의 하드웨어 리소스 제한에 배경이 있다. 컴파일에는 많은 작업을 수행하는 것이 포함되며 초기 컴퓨터는 이 모든 작업을 수행하는 하나의 프로그램을 포함하기에 충분한 메모리를 가지고 있지 않았다. 그래서 컴파일러는 작은 프로그램으로 나뉘어져서 각각 필요한 분석과 번역을 수행하는 소스(또는 그것의 일부 표현)를 통과했다.

컴파일러 쓰기 작업을 단순화하고 일반적으로 멀티패스 컴파일러보다 더 빠른 컴파일을 수행하기 때문에 단일 패스 컴파일러로 컴파일할 수 있는 능력은 고전적으로 이익으로 여겨져 왔다. 따라서, 초기 시스템의 자원 한계에 의해 부분적으로 구동되는 많은 초기 언어들은 단일 패스(예: 파스칼)로 컴파일될 수 있도록 특별히 설계되었다.

경우에 따라 언어 기능의 설계는 컴파일러가 소스 위로 두 개 이상의 패스를 수행해야 할 수 있다. 예를 들어, 10번 라인에 나타나는 문장의 번역에 영향을 미치는 출처의 20번 라인에 나타나는 선언을 고려하십시오. 이 경우 첫 번째 패스는 이후 패스에서 실제 번역이 이뤄지는 등 영향을 미치는 문장 뒤에 나타나는 선언에 대한 정보를 수집할 필요가 있다.

단일 패스로 컴파일할 때의 단점은 고품질 코드를 생성하는 데 필요한 정교한 최적화를 많이 수행할 수 없다는 점이다. 최적화하는 컴파일러가 얼마나 많은 패스를 하는지 정확히 계산하기는 어려울 수 있다. 예를 들어, 최적화의 다른 단계는 한 표현식을 여러 번 분석할 수 있지만 다른 표현식은 한 번만 분석할 수 있다.

컴파일러를 작은 프로그램으로 나누는 것은 확실히 정확한 컴파일러를 생산하는 데 관심이 있는 연구자들에 의해 사용되는 기술이다. 작은 프로그램 세트의 정확성을 증명하는 것은 종종 더 크고 동등한 단일 프로그램의 정확성을 증명하는 것보다 적은 노력을 필요로 한다.

3단 컴파일러 구조

컴파일러 설계

컴파일러 설계의 정확한 위상 수와 관계없이 위상은 세 단계 중 하나에 할당할 수 있다. 무대에는 프런트엔드, 미드엔드, 백엔드가 있다.

  • 프런트 엔드는 입력을 스캔하여 특정 소스 언어에 따라 구문과 의미론을 확인한다. 정적으로 입력된 언어의 경우 유형 정보를 수집하여 유형 확인을 수행한다. 입력 프로그램이 구문적으로 부정확하거나 형식 오류가 있는 경우 오류 및/또는 경고 메시지를 생성하며, 일반적으로 문제가 탐지된 소스 코드에서 위치를 식별한다. 경우에 따라 실제 오류는 프로그램 초기에 발생할 수 있다. 프런트 엔드의 측면으로는 어휘 분석, 구문 분석, 의미 분석 등이 있다. 프런트 엔드는 중간 엔드까지 추가 처리를 위해 입력 프로그램을 중간 표현(IR)으로 변환한다. 이 IR은 보통 소스 코드에 관한 프로그램을 하위 수준으로 나타낸다.
  • 중간 끝은 대상 CPU 아키텍처와 독립된 IR에서 최적화를 수행한다. 이러한 소스 코드/머신 코드 독립성은 다른 언어와 타겟 프로세서를 지원하는 컴파일러 버전 간에 일반 최적화가 공유될 수 있도록 하기 위한 것이다. 미들엔드 최적화의 예로는 쓸모없는(데드 코드 제거) 또는 도달할 수 없는 코드(접근성 분석), 상수 값의 발견과 전파(정수 전파), 덜 자주 실행되는 장소로의 연산 재배치(예: 루프 아웃) 또는 문맥에 기초한 연산 전문화가 있다. 결국 백엔드에 의해 사용되는 "최적화된" IR을 생산한다.
  • 백엔드는 최적화된 IR을 미들엔드에서 가져간다. 대상 CPU 아키텍처에 특정한 더 많은 분석, 변환 및 최적화를 수행할 수 있다. 백엔드는 대상 종속 어셈블리 코드를 생성하여 프로세스에서 레지스터 할당을 수행한다. 백엔드는 명령 스케줄링을 수행하며, 명령어는 지연 슬롯을 채움으로써 병렬 실행 단위를 계속 사용 가능하도록 순서를 변경한다. 최적화 문제는 대부분 NP-hard이지만 이를 해결하기 위한 휴리스틱 기법이 잘 개발되어 현재 생산 품질 컴파일러에서 구현되고 있다. 일반적으로 백엔드의 출력은 특정 프로세서와 운영 체제에 특화된 기계 코드다.

이러한 프런트/미들/백엔드 접근방식은 다른 언어의 프런트 엔드(front end)와 다른 CPU의 백 엔드를 결합하는 동시에 미들엔드의 최적화를 공유할 수 있게 한다.[39] 이 접근방식의 실제적인 예는 GNU 컴파일러 컬렉션, 클랑(LLVM 기반 C/C++ 컴파일러)[40]암스테르담 컴파일러 키트(여러 개의 프런트 엔드, 공유 최적화, 다중 백엔드)가 있다.

프런트 엔드

C에 대한 렉서파서 예제. 문자 시퀀스 "부터 시작if(net>0.0)total+=net*(1.0+tax/100.0);" 스캐너는 일련의 토큰을 구성하고, 각각 식별자, 예약된 단어, 숫자 리터럴 또는 연산자로 분류한다. 후자의 순서는 파서에 의해 구문 트리로 변환되며, 그 후 나머지 컴파일러 단계에 의해 처리된다. 스캐너와 파서는 각각 C의 문법에서 문법이 규칙적이고 문맥이 없는 부분을 처리한다.

프런트 엔드는 소스코드를 분석하여 중간표현(IR)이라 불리는 프로그램의 내부표현을 구축한다. 또한 위치, 유형, 범위 등 관련 정보에 소스 코드의 각 기호를 매핑하는 데이터 구조인 기호 표도 관리한다.

프런트엔드는 스캐너리스 파서처럼 단일 단일 기능이나 프로그램일 수 있지만, 전통적으로 순차적으로 또는 동시에 실행할 수 있는 여러 단계로 구현 및 분석되었다. 이 방법은 모듈화와 우려의 분리 때문에 선호된다. 오늘날 가장 보편적으로 프런트엔드는 어휘 분석(렉싱 또는 스캔이라고도 함), 구문 분석(스캔 또는 파싱이라고도 함), 의미 분석의 3단계로 구분된다. 렉싱과 파싱은 구문 분석(각각 단어 구문 및 구문 구문)으로 구성되며, 간단한 경우 이러한 모듈(렉서 및 파서)은 언어의 문법에서 자동으로 생성될 수 있지만, 더 복잡한 경우에는 수동 수정이 필요하다. 어휘문법과 구문법은 보통 문맥이 없는 문법으로서, 의미분석 단계에서 처리되는 문맥감성으로 분석을 상당히 단순화한다. 의미론적 분석 단계는 일반적으로 더 복잡하고 손으로 작성되지만 속성 그래머를 사용하여 부분적으로 또는 완전히 자동화할 수 있다. 이러한 단계 자체는 더 세분화될 수 있다. 즉, 스캔 및 평가로 렉싱하고, 콘크리트 구문 트리(CST, 구문 트리)를 구축한 추상 구문 트리(AST, 구문 트리)로 변환하는 파싱이다. 특히 선 재구성전처리 등 추가 단계를 사용하는 경우도 있지만, 이러한 경우는 드물다.

프런트 엔드의 주요 단계는 다음과 같다.

  • 라인 재구성은 입력 문자 시퀀스를 파서를 위한 표준 형식으로 변환한다. 키워드를 삽입하거나 식별자 내에 임의의 공간을 허용하는 언어에는 이 단계가 필요하다. 1960년대에 사용된 하향식 재귀성 테이블 기반 파서들은 일반적으로 한 번에 한 글자씩 출처를 읽으며 별도의 토큰화 단계가 필요하지 않았다. 아틀라스 오토코드imf(및 ALGOLCoral 66의 일부 구현)는 컴파일러가 라인 재구성 단계를 갖는 스트로빙 언어의 예다.
  • 사전 처리는 매크로 대체와 조건부 컴파일을 지원한다. 전형적으로 전처리 단계는 통사적 또는 의미적 분석 전에 발생한다. 예를 들어, C의 경우, 전처리가 통사적 형식이 아닌 어휘적 토큰을 조작한다. 그러나 Scheme과 같은 몇몇 언어들은 통사적 형태에 기초한 매크로 대체물을 지원한다.
  • 어휘 분석(렉싱 또는 토큰화라고도 함)은 소스 코드 텍스트를 어휘 토큰이라고 하는 일련의 작은 조각으로 구분한다.[41] 이 단계는 입력 텍스트를 어휘소라는 통사적 단위로 분할하여 범주를 할당하는 스캐닝과 어휘소를 처리된 값으로 변환하는 평가의 두 단계로 나눌 수 있다. 토큰은 토큰 이름과 선택적 토큰 값으로 구성된 쌍이다.[42] 토큰 범주의 집합은 프로그래밍 언어마다 다르지만 공통 토큰 범주는 식별자, 키워드, 구분자, 연산자, 리터럴 및 코멘트를 포함할 수 있다. 어휘소 구문은 전형적으로 정규 언어여서 정규 표현식으로 구성된 유한 상태 자동화를 사용하여 이를 인식할 수 있다. 어휘 분석을 하는 소프트웨어는 어휘 분석기라고 불린다. 이것은 별도의 단계가 아닐 수도 있다. 스캐너리스 파싱의 파싱 단계와 결합할 수 있다. 이 경우 파싱은 토큰 레벨이 아닌 문자 레벨에서 이루어진다.
  • 구문 분석(파싱이라고도 함)은 프로그램의 구문 구조를 식별하기 위해 토큰 시퀀스를 구문 분석하는 것을 포함한다. 이 단계는 전형적으로 파스 트리를 형성하는데, 이것은 언어의 구문을 정의하는 공식 문법의 규칙에 따라 만들어진 트리 구조로 토큰의 선형 순서를 대체한다. 파스 트리는 컴파일러의 후기 단계에 의해 분석, 증강 및 변환되는 경우가 많다.[43]
  • 의미 분석파스 트리에 의미 정보를 추가하고 기호 표를 구축한다. 이 단계는 유형 확인(유형 오류 확인) 또는 객체 바인딩(변수와 함수 참조를 정의와 연결) 또는 확정 할당(사용 전에 모든 로컬 변수를 초기화해야 함)과 같은 의미론적 확인을 수행하며, 잘못된 프로그램을 거부하거나 경고를 발령한다. 의미론적 분석에는 일반적으로 완전한 파스 트리가 필요하며, 이는 컴파일러 구현에서 코드 위에 여러 단계를 하나의 패스로 접는 것이 가능하지만, 이 단계가 논리적으로 파싱 단계를 따르고, 논리적으로 코드 생성 단계를 선행한다는 것을 의미한다.

미들엔드

Optimizer라고도 알려진 중간 끝은 생산된 기계 코드의 성능과 품질을 개선하기 위해 중간 표현에서 최적화를 수행한다.[44] 중간 끝에는 대상 CPU 아키텍처와 독립적인 최적화가 포함되어 있다.

중간 끝의 주요 단계는 다음과 같다.

컴파일러 분석은 모든 컴파일러 최적화의 전제조건이며, 그들은 긴밀하게 협력한다. 예를 들어, 의존성 분석루프 변환에 매우 중요하다.

컴파일러 분석 및 최적화의 범위는 매우 다양하다. 컴파일러의 범위는 기본 블록 내에서 작동하는 것에서부터 전체 절차 또는 전체 프로그램에 이르기까지 다양할 수 있다. 최적화의 세분화와 컴파일 비용 사이에는 절충이 있다. 예를 들어, 핍홀 최적화는 컴파일 중에 수행이 빠르지만 코드의 작은 국소 조각에만 영향을 미치며, 코드 조각이 나타나는 맥락과는 무관하게 수행될 수 있다. 와는 대조적으로, 절차간 최적화는 더 많은 컴파일 시간과 메모리 공간이 필요하지만, 동시에 복수의 기능의 동작을 고려해야만 가능한 최적화를 가능하게 한다.

절차간 분석과 최적화는 HP, IBM, SGI, Intel, Microsoft, Sun Microsystems의 현대 상용 컴파일러에서 흔히 볼 수 있다. 무료 소프트웨어 GCC는 강력한 절차간 최적화가 부족하다는 지적을 오랫동안 받았지만, 이런 측면에서 바뀌고 있다. 완전한 분석과 최적화 인프라를 갖춘 또 다른 오픈 소스 컴파일러는 Open64로, 많은 조직에서 연구와 상업적 목적으로 사용되고 있다.

컴파일러 분석과 최적화에 필요한 추가 시간과 공간 때문에 일부 컴파일러는 기본적으로 이를 건너뛰기도 한다. 사용자는 컴파일러에게 어떤 최적화가 활성화되어야 하는지 명시적으로 알려주기 위해 컴파일러 옵션을 사용해야 한다.

백엔드

백엔드는 CPU 아키텍처별 최적화 및 코드 생성[44] 담당한다.

백엔드의 주요 단계는 다음과 같다.

  • 시스템 종속 최적화: 컴파일러가 대상으로 하는 CPU 아키텍처의 세부 정보에 따라 달라지는 최적화.[45] 대표적인 예가 핍홀 최적화인데, 이는 조립자 지침의 짧은 시퀀스를 보다 효율적인 지침으로 다시 작성한다.
  • 코드 생성: 변환된 중간 언어는 출력 언어, 대개 시스템의 기본 기계 언어로 번역된다. 여기에는 레지스터와 메모리에 장착할 변수를 결정하고 관련 주소 지정 모드와 함께 적절한 기계 지침의 선택스케줄링과 같은 자원 및 저장 결정이 포함된다(Sethi-Ulman 알고리즘 참조). 디버깅을 용이하게 하기 위해 디버그 데이터를 생성해야 할 수도 있다.

컴파일러 정확성

컴파일러의 정확성은 컴파일러가 언어 사양에 따라 동작한다는 것을 보여주는 시도를 다루는 소프트웨어 엔지니어링의 한 분야다.[citation needed] 기법에는 형식적인 방법을 사용하여 컴파일러를 개발하고 기존 컴파일러에 대해 엄격한 테스트(종종 컴파일러 유효성 검사라고 함)를 사용하는 것이 포함된다.

컴파일된 언어와 해석된 언어

더 높은 수준의 프로그래밍 언어는 보통 컴파일된 언어 또는 해석된 언어로 설계된 번역의 유형을 염두에 두고 나타난다. 그러나 실제로는 런타임에 재해석에 의존하는 언어를 설계하는 것은 가능하지만, 그것을 배타적으로 컴파일하거나 배타적으로 해석하도록 요구하는 언어에 대해서는 거의 없다. 이 분류는 일반적으로 가장 대중적이거나 광범위한 언어 구현을 반영한다. 예를 들어, BASIC 컴파일러와 C 통역사가 존재함에도 불구하고 BASIC은 해석된 언어라고 불리고, C는 편집된 언어라고 불린다.

해석이 편찬을 완전히 대체하는 것은 아니다. 사용자로부터 숨기고 점진적으로 만들 뿐이다. 통역자 자체가 해석될 수 있지만, 실행 스택의 하단 어딘가에 직접 실행된 프로그램이 필요하다(기계 언어 참조).

또한 최적화 컴파일러는 통역 기능성을 포함할 수 있으며, 통역사는 미리 컴파일 기법을 포함할 수 있다. 예를 들어 컴파일 중에 식을 실행할 수 있고 출력 프로그램에 결과를 삽입할 수 있는 경우 프로그램이 실행될 때마다 식을 다시 계산해야 하는 것을 방지하여 최종 프로그램의 속도를 크게 높일 수 있다. 때마침 정시의 컴파일바이트코드 해석에 대한 현대의 경향은 컴파일러와 통역사의 전통적인 분류 체계를 더욱 흐리게 한다.

일부 언어 규격은 를 들어, Common Lisp과 같은 컴파일 기능을 구현해야 을 명시한다. 그러나 Common Lisp의 정의에는 그것을 해석하는 것을 막는 본질적인 것은 없다. 다른 언어들은 통역기에서 구현하기 매우 쉽지만 컴파일러 쓰기를 훨씬 어렵게 만드는 특징을 가지고 있다. 예를 들어, APL, OPESTOL4 및 많은 스크립팅 언어는 프로그램이 정규 문자열 연산을 통해 런타임에 임의의 소스 코드를 구성하도록 허용한 다음, 그것을 특수한 평가 함수에 전달하여 코드를 실행시킨다. 컴파일된 언어로 이러한 기능을 구현하려면 일반적으로 프로그램은 컴파일러 자체의 버전을 포함하는 런타임 라이브러리와 함께 제공되어야 한다.

종류들

컴파일러의 한 분류는 생성된 코드가 실행되는 플랫폼에 의해 이루어진다. 이것을 타겟 플랫폼이라고 한다.

네이티브 컴파일러 또는 호스트 컴파일러는 컴파일러 자체가 실행되는 동일한 유형의 컴퓨터 및 운영 체제에서 직접 실행되도록 출력된 컴파일러를 말한다. 크로스 컴파일러의 출력은 다른 플랫폼에서 실행되도록 설계되었다. 크로스 컴파일러는 소프트웨어 개발 환경을 지원하기 위한 것이 아닌 임베디드 시스템용 소프트웨어를 개발할 때 종종 사용된다.

가상 머신(VM)용 코드를 생성하는 컴파일러의 출력은 이를 생성한 컴파일러와 동일한 플랫폼에서 실행되거나 실행되지 않을 수 있다. 이러한 이유로, 그러한 컴파일러는 보통 네이티브 컴파일러나 크로스 컴파일러로 분류되지 않는다.

컴파일러의 대상인 하급 언어 자체가 고급 프로그래밍 언어일 수 있다. 일부에서 휴대용 조립 언어의 일종으로 보는 C는 그러한 컴파일러의 목표 언어인 경우가 많다. 예를 들어 C++의 원래 컴파일러인 Cfront는 C를 대상 언어로 사용했다. 그러한 컴파일러에 의해 생성되는 C 코드는 대개 판독이 가능하고 인간에 의해 유지되는 것이 아니기 때문에 들여쓰기 스타일과 예쁜 C 중간 코드를 만드는 것은 무시된다. 그것을 좋은 타겟언어로 만드는 C의 특징으로는 원래 소스의 디버깅을 지원하기 위해 컴파일러에 의해 생성될 수 있는 지시어와 C 컴파일러와 함께 사용할 수 있는 넓은 플랫폼 지원이 있다.

공통 컴파일러 타입은 기계코드를 출력하지만, 다른 타입도 많다.

  • 소스 대 소스 컴파일러는 하이 레벨 언어를 입력으로 삼고 하이 레벨 언어를 출력하는 컴파일러의 일종이다. 예를 들어 자동 병렬화 컴파일러는 입력으로 고급 언어 프로그램을 자주 취하다가 코드를 변환하여 병렬 코드 주석(예: OpenMP)이나 언어 구성(예: Fortran's)으로 주석을 달게 된다. DOALL 진술서). 소스 대 소스 컴파일러의 다른 용어는 언어 번역기, 언어 변환기 또는 언어 리라이터이다.[citation needed] 마지막 용어는 보통 언어의 변화를 수반하지 않는 번역에 적용된다.[46]
  • 바이트 코드 컴파일러는 일부 Prolog 구현과 같은 이론적 기계의 어셈블리 언어로 컴파일
  • JIT 컴파일러(JIT 컴파일러)는 실행 시간까지 컴파일을 연기한다. JIT 컴파일러는 파이톤, 자바스크립트, 스몰토크, 자바, 마이크로소프트를 포함한 많은 현대 언어들을 위해 존재한다.NETCIL(Common Intermediate Language) 및 기타 JIT 컴파일러는 일반적으로 통역사 안에서 작동한다. 통역사가 코드 경로가 자주 실행되는 것을 의미하는 "hot"임을 감지하면 JIT 컴파일러를 호출하여 "hot" 코드를 컴파일하여 성능을 향상시킨다.
    • 자바와 같은 일부 언어의 경우, 애플리케이션은 먼저 바이트코드 컴파일러를 사용하여 컴파일되고 기계에 독립적인 중간표시로 전달된다. 바이트코드 통역기는 바이트코드를 실행하지만, JIT 컴파일러는 성능 향상이 필요할 때 바이트코드를 기계코드로 변환한다.[47][non-primary source needed]
  • 하드웨어 컴파일러(합성 도구라고도 함)는 입력이 하드웨어 설명 언어이고 출력이 하드웨어 구성의 설명인 컴파일러다.
  • 조립자는 사람이 읽을 수 있는 조립 언어기계 코드로 컴파일하는 프로그램이며, 하드웨어에 의해 실행된 실제 지시사항이다. 기계 코드를 조립 언어로 번역하는 역 프로그램을 디스어셈블러라고 한다.
  • 낮은 수준의 언어에서 높은 수준의 언어로 번역하는 프로그램이 디컴파일러다.[citation needed]
  • 컴파일 머신에서 지원되지 않는 객체 코드 포맷으로 번역하는 프로그램을 크로스 컴파일러라고 하며 임베디드 어플리케이션의 코드를 준비하는 데 흔히 사용된다.[citation needed][clarification needed]
  • 최적화와 변환을 적용하면서 동일한 유형의 개체 코드로 객체 코드를 다시 쓰는 프로그램이 바이너리 재컴파일러다.

참고 항목

참조

  1. ^ PC Mag Staff (28 February 2019). "Encyclopedia: Definition of Compiler". PCMag.com. Retrieved 28 February 2017.
  2. ^ a b 컴파일러: 알프레드 5세의 원리, 기술, 도구. 아호, 라비 세티, 제프리 D. Ulman - Second Edition, 2007
  3. ^ Sun, Chengnian; Le, Vu; Zhang, Qirun; Su, Zhendong (2016). "Toward Understanding Compiler Bugs in GCC and LLVM". ACM.
  4. ^ 강의 노트: 컴퓨터 과학 & 정보 공학 국립 치난 대학교의 원칙, 기술, 도구 징-신창 학부
  5. ^ 나우르, P. 외 "ALLGOL 60에 관한 보고서" ACM 3 (1960년 5월), 299–314의 통신.
  6. ^ Chomsky, Noam; Lightfoot, David W. (2002). Syntactic Structures. Walter de Gruyter. ISBN 978-3-11-017279-9.
  7. ^ Gries, David (2012). "Appendix 1: Backus-Naur Form". The Science of Programming. Springer Science & Business Media. p. 304. ISBN 978-1461259831.
  8. ^ Iverson, Kenneth E. (1962). A Programming Language. John Wiley & Sons. ISBN 978-0-471430-14-8.
  9. ^ Backus, John. "The history of FORTRAN I, II and III" (PDF). History of Programming Languages. Softwarepreservation.org.
  10. ^ 포터 아담스, 비키(1981년 10월 5일). "그레이스 M 대위. 호퍼: 코볼의 어머니" InfoWorld. 3(20): 33. ISSN 0199-6649.
  11. ^ 매카시, J.; 브레이튼, 에드워드, 폭스, P.; 호드, L.; 럭햄, D.; 말링, K.; 파크, D.; 러셀, S. (1960년 3월) "LISP I 프로그래머 설명서"(PDF) 매사추세츠 주 보스턴: 인공지능 그룹, M.I.T. 연산센터 및 연구실.
  12. ^ 컴파일러 원칙, 기법 및 도구 2판 아호, 람, 세티, 울만 ISBN 0-321-48681-1
  13. ^ Hopper, Grace Murray (1952). "The Education of a Computer". Proceedings of the 1952 ACM National Meeting (Pittsburgh): 243–249. doi:10.1145/609784.609818. S2CID 10081016.
  14. ^ Ridgway, Richard K. (1952). "Compiling routines". Proceedings of the 1952 ACM National Meeting (Toronto): 1–5. doi:10.1145/800259.808980. S2CID 14878552.
  15. ^ ACM 통신, 1960년 4월 "기계별 기호표현계산의 반복 기능"
  16. ^ McCarthy, John; Abrahams, Paul W.; Edwards, Daniel J.; Hart, Timothy P.; Levin, Michael I. (1965). Lisp 1.5 Programmers Manual. The MIT Press. ISBN 9780262130110.
  17. ^ "BCPL: 컴파일러 쓰기시스템 프로그래밍을 위한 도구" M. Richards, University Mathemical Laboratory Cambridge, 영국 1969
  18. ^ BCPL: The Language and its Compiler, M Richards, Cambridge University Press(1981년 12월 31일 처음 출판)
  19. ^ 2017년 M. Richards의 BCPL Cintsys 및 Cintpos 사용자 설명서
  20. ^ Corbató, F. J.; Vyssotsky, V. A. "Introduction and Overview of the MULTICS System". 1965 Fall Joint Computer Conference. Multicians.org.
  21. ^ SHARE 고급 언어 개발 위원회 보고서 II, 1964년 6월 25일
  22. ^ Multicians.org "PL/I의 선택" 기사, 편집자 /tom Van Vleck
  23. ^ "시스템 프로그래밍의 도구로서 PL/I As a Tool," F.J. Corbato, Datamisation 6 1969년 5월 6일 발행
  24. ^ "멀틱스 PL/1 컴파일러", R. A. 프라이부르크, GE, Fall Joint Computer Conference 1969
  25. ^ 데이터 입력란, 1969
  26. ^ 데니스 M. 리치, "C언어의 발전", ACM 제2회 프로그래밍 언어 콘퍼런스, 1993년 4월
  27. ^ SC 존슨 "휴대용 C 컴파일러: 제5회 ACM POPL 심포지엄, 1978년 1월
  28. ^ A. Snyder, A Portable Compiler for the Language C, MIT, 1974.
  29. ^ K. Nygarard, 노르웨이 오슬로 대학교, "객체 지향 프로그래밍의 기본 개념", SIGPlan 공지 V21, 1986
  30. ^ B. 스트루스트럽: "객체 지향 프로그래밍이란 무엇인가?" 제14차 ASU 회의, 1986.
  31. ^ Bjarne Stroustrup, "An Overview of the C++ Programming Language", Handbook of Object Technology(편집자: Saba Zamir, ISBN 0-8493-3135-8)
  32. ^ 레베렛, 캣텔, 홉스, 신참, 라이너, 샤츠, 울프: CMU-CS-89-105, 1979년 "생산품질 컴파일러-컴파일러 프로젝트 개요"
  33. ^ W. 울프, K. Nori, "PQCC 생성 컴파일러에서 지연된 바인딩", CMU-CS-82-138, 1982년 CMU 연구 쇼케이스 보고서
  34. ^ 조셉 M. 새로 온 데이비드 알렉스 램, 브루스 W. 레베트, 마이클 티게, 윌리엄 A. 울프 - 카네기-멜론 대학교 및 데이비드 레빈, 앤드류 H. 레이너릿 - 상호 측정학: "TCOL Ada: DOD 표준 프로그래밍 언어의 중간 표현에 관한 수정된 보고서", 1979년
  35. ^ 윌리엄 A. Whitaker, "Ada - 프로젝트: DoD High Order Working Group", ACM SIGLAN 공지사항 (제28권, 제3권, 1991년 3월)
  36. ^ CECOM Center for Software Engineering Advanced Software Technology, "Final Report - Real-Time Applications용 ACEC Benchmark Suite의 평가", AD-A231 968, 1990
  37. ^ P.Biggar, E. de Vries, D. Greggg, "스크립팅 언어 컴파일러를 위한 실용적인 솔루션", 2009년 컴퓨터 프로그래밍 과학에 제출
  38. ^ M.Hall, D. Padua, K. Pingali, "Compiler Research: 향후 50년", ACM Communications 2009 Vol 54 #2
  39. ^ 쿠퍼와 토르손 2012, 페이지 8
  40. ^ Lattner, Chris (2017). "LLVM". In Brown, Amy; Wilson, Greg (eds.). The Architecture of Open Source Applications. Archived from the original on 2 December 2016. Retrieved 28 February 2017.
  41. ^ 아호, 람, 세티, 울만 2007, 페이지 5-6, 109-189
  42. ^ 아호, 람, 세티, 울만 2007, 페이지 111
  43. ^ 아호, 람, 세티, 울만 2007, 페이지 8, 191-300
  44. ^ a b Blindell, Gabriel Hjort (3 June 2016). Instruction selection : principles, methods, and applications. Switzerland. ISBN 9783319340197. OCLC 951745657.
  45. ^ 쿠퍼와 토크존(2012), 페이지 540
  46. ^ "Language Translator Tutorial" (PDF). Washington University.
  47. ^ Aycock, John (2003). "A Brief History of Just-in-Time". ACM Comput. Surv. 35 (2, June): 93–113. doi:10.1145/857076.857077. S2CID 15345671.[비확산 소스 필요]
  48. ^ Swartz, Jordan S.; Betz, Vaugh; Rose, Jonathan (22–25 February 1998). "A Fast Routability-Driven Router for FPGAs" (PDF). FPGA '98 Proceedings of the 1998 ACM/SIGDA Sixth International Symposium on Field Programmable Gate Arrays. Monterey, CA: ACM: 140–149. doi:10.1145/275107.275134. ISBN 978-0897919784. S2CID 7128364. Archived (PDF) from the original on 9 August 2017.
  49. ^ Xilinx Staff (2009). "XST Synthesis Overview". Xilinx, Inc. Archived from the original on 2 November 2016. Retrieved 28 February 2017.[비확산 소스 필요]
  50. ^ Altera Staff (2017). "Spectra-Q™ Engine". Altera.com. Archived from the original on 10 October 2016. Retrieved 28 February 2017.[비확산 소스 필요]

추가 읽기

외부 링크