Коллекция компиляторов GNU ( GCC ) — это оптимизирующий компилятор , созданный проектом GNU Project , поддерживающий различные языки программирования , аппаратные архитектуры и операционные системы . Фонд свободного программного обеспечения (FSF) распространяет GCC как бесплатное программное обеспечение под лицензией GNU General Public License (GNU GPL). GCC — ключевой компонент инструментальной цепочки GNU и стандартный компилятор для большинства проектов, связанных с GNU и ядром Linux . GCC, насчитывающая примерно 15 миллионов строк кода в 2019 году, является одной из крупнейших существующих бесплатных программ. [4] Оно сыграло важную роль в развитии свободного программного обеспечения как инструмент и пример.
Когда он был впервые выпущен в 1987 году Ричардом Столлманом , GCC 1.0 назывался компилятором GNU C , поскольку он работал только с языком программирования C. [1] В декабре того же года он был расширен для компиляции C++ . Позднее интерфейсы были разработаны для Objective-C , Objective-C++ , Fortran , Ada , D , Go и Rust , [6] среди других. [ 7] Спецификации OpenMP и OpenACC также поддерживаются компиляторами C и C++. [8] [9]
GCC портирован на большее количество платформ и архитектур набора команд , чем любой другой компилятор, и широко используется в качестве инструмента при разработке как свободного, так и несвободного программного обеспечения . GCC также доступен для многих встроенных систем , включая чипы на базе ARM и Power ISA .
Будучи официальным компилятором операционной системы GNU , GCC был принят в качестве стандартного компилятора многими другими современными Unix-подобными компьютерными операционными системами , включая большинство дистрибутивов Linux . Большинство операционных систем семейства BSD также перешли на GCC вскоре после его выпуска, хотя с тех пор FreeBSD , OpenBSD и Apple macOS перешли на компилятор Clang [10] во многом по причинам лицензирования. [11] [12] [13] GCC также может компилировать код для Windows , Android , iOS , Solaris , HP-UX , AIX и DOS . [14]
В конце 1983 года, пытаясь запустить операционную систему GNU , Ричард Столлман попросил Эндрю С. Таненбаума , автора Амстердамского компилятора (также известного как Free University Compiler Kit ), получить разрешение на использование этого программного обеспечения для GNU. Когда Таненбаум сообщил ему, что компилятор не является бесплатным и что бесплатным является только университет, Столлман решил работать над другим компилятором. [15] Его первоначальный план состоял в том, чтобы переписать существующий компилятор из Ливерморской национальной лаборатории Лоуренса с Pastel на C с некоторой помощью Лена Тауэра и других. [16] [17] Столлман написал новый интерфейс C для ливерморского компилятора, но затем понял, что для этого требуются мегабайты стекового пространства, что невозможно в системе Unix 68000 с размером всего 64 КБ, и пришел к выводу, что ему придется написать новый компилятор с нуля. [16] Ни один из кодов компилятора Pastel не попал в GCC, хотя Столлман действительно использовал написанный им интерфейс C. [16] [18]
GCC был впервые выпущен 22 марта 1987 года и доступен по FTP от MIT . [19] Столлман был указан в качестве автора, но процитировал других за их вклад, в том числе Тауэра за «части синтаксического анализатора, генератора RTL, определений RTL и описания машины Vax», Джека Дэвидсона и Кристофера В. Фрейзера за идею использование RTL в качестве промежуточного языка и Пола Рубина для написания большей части препроцессора. [20] Описанный Питером Х. Салусом как «первый хит свободного программного обеспечения» , компилятор GNU появился как раз в то время, когда Sun Microsystems отделяла свои инструменты разработки от своей операционной системы , продавая их отдельно по более высокой совокупной цене, чем предыдущий. Bundle, из-за чего многие пользователи Sun покупали или загружали GCC вместо инструментов этого поставщика. [21] Хотя Столлман считал GNU Emacs своим основным проектом, к 1990 году GCC поддерживал тринадцать компьютерных архитектур, превосходил по производительности компиляторы нескольких поставщиков и использовался в коммерческих целях несколькими компаниями. [22]
Поскольку GCC лицензировался под лицензией GPL, программисты, желающие работать в других направлениях — особенно те, кто писал интерфейсы для языков, отличных от C, — могли свободно разрабатывать свою собственную вилку компилятора при условии, что они соответствуют условиям GPL, включая ее требования по распространению исходного кода . код . Однако многочисленные форки оказались неэффективными и громоздкими, а трудности с принятием работы официальным проектом GCC сильно расстраивали многих, поскольку в проекте предпочтение отдавалось стабильности новым функциям. [23] FSF настолько тщательно контролировал то, что было добавлено к официальной версии GCC 2.x (разрабатываемой с 1992 года), что GCC использовался как один из примеров «соборной» модели разработки в эссе Эрика С. Рэймонда « The Собор и базар .
В 1997 году группа разработчиков сформировала Экспериментальную/расширенную систему компиляторов GNU (EGCS) , чтобы объединить несколько экспериментальных версий в один проект. [23] [18] Основой слияния стал снимок разработки GCC (сделанный примерно в версии 2.7.2, а затем до версии 2.8.1). Слияния включали g77 (Fortran), PGCC ( GCC, оптимизированный для P5 Pentium ), [18] множество улучшений C++, а также множество новых архитектур и вариантов операционных систем . [24]
Хотя оба проекта внимательно следили за изменениями друг друга, разработка EGCS оказалась значительно более энергичной, настолько, что FSF официально остановил разработку своего компилятора GCC 2.x, благословил EGCS как официальную версию GCC и назначил проект EGCS GCC. сопровождающие в апреле 1999 года. С выпуском GCC 2.95 в июле 1999 года два проекта снова были объединены. [25] [18] С тех пор GCC поддерживается разнообразной группой программистов со всего мира под руководством руководящего комитета. [26]
В GCC 3 (2002 г.) удален интерфейс для CHILL из-за отсутствия обслуживания. [27]
До версии 4.0 интерфейсом Fortran был g77
, который поддерживал только FORTRAN 77 , но позже от него отказались в пользу нового интерфейса GNU Fortran , который поддерживает Fortran 95 , а также большую часть Fortran 2003 и Fortran 2008 . [28] [29]
Начиная с версии 4.8, GCC реализован на C++. [30]
Поддержка Cilk Plus существовала с GCC 5 по GCC 7. [31] [32]
GCC был портирован на самые разные архитектуры наборов команд и широко используется в качестве инструмента при разработке как свободного, так и несвободного программного обеспечения . GCC также доступен для многих встроенных систем , включая Symbian (называемый gcce ), [33] чипы на базе ARM и Power ISA . [34] Компилятор может работать с широким спектром платформ, включая игровые консоли , такие как PlayStation 2 , [35] Cell SPE для PlayStation 3, [36] и Dreamcast . [37] Он был портирован на большее количество процессоров и операционных систем, чем любой другой компилятор. [38] [ собственный источник? ] [ нужен лучший источник ]
Начиная с версии 13.1, [обновлять]GCC включает интерфейсы для C ( gcc
), C++ ( g++
), Objective-C и Objective-C++ , Fortran ( gfortran
), Ada ( GNAT ), Go ( gccgo
), D ( gdc
, начиная с версии 9.1), [39] [40] и Modula-2 ( gm2
, начиная с версии 13.1) [41] [42] языки программирования, [43] с расширениями параллельного языка OpenMP и OpenACC , поддерживаемыми начиная с GCC 5.1. [9] [44] Версии до GCC 7 также поддерживали Java ( gcj
), позволяя компилировать Java в собственный машинный код. [45]
Что касается поддержки языковых версий для C++ и C, начиная с GCC 11.1 целью по умолчанию является gnu++17 , расширенный набор C++17 , и gnu11 , расширенный набор C11 , также доступна строгая стандартная поддержка. GCC также предоставляет экспериментальную поддержку C++20 и C++23 . [46]
Сторонние интерфейсы существуют для многих языков, таких как Pascal ( gpc
), Modula-3 и VHDL ( GHDL
). [43] Существует несколько экспериментальных веток для поддержки дополнительных языков, таких как компилятор GCC UPC для Unified Parallel C [47] или Rust . [48] [49] [50] [ нужен лучший источник ]
Внешний интерфейс GCC соответствует соглашениям Unix . Пользователи вызывают программу-драйвер для конкретного языка ( gcc
для C, g++
для C++ и т. д.), которая интерпретирует аргументы команды , вызывает фактический компилятор, запускает ассемблер на выходе, а затем, при необходимости, запускает компоновщик для создания полного исполняемого двоичного файла.
Каждый из компиляторов языка представляет собой отдельную программу, считывающую исходный код и выдающую машинный код . Все они имеют общую внутреннюю структуру. Интерфейсная часть для каждого языка анализирует исходный код на этом языке и создает абстрактное синтаксическое дерево («дерево» для краткости).
При необходимости они преобразуются во входное представление промежуточного конца, называемое ОБЩЕЙ формой; затем средний конец постепенно преобразует программу к ее окончательной форме. К коду применяются оптимизации компилятора и методы статического анализа кода (такие как FORTIFY_SOURCE, [51] директива компилятора, которая пытается обнаружить некоторые случаи переполнения буфера ). Они работают с несколькими представлениями, в основном с независимым от архитектуры представлением GIMPLE и зависящим от архитектуры представлением RTL . Наконец, машинный код создается с использованием сопоставления шаблонов с учетом особенностей архитектуры , первоначально основанного на алгоритме Джека Дэвидсона и Криса Фрейзера.
GCC был написан в основном на C , за исключением частей интерфейса Ada . В дистрибутив входят стандартные библиотеки для Ada и C++ , код которых в основном написан на этих языках. [52] [ нужно обновить ] На некоторых платформах в дистрибутив также входит низкоуровневая библиотека времени выполнения libgcc , написанная на комбинации машинно-независимого C и машинного кода , специфичного для процессора , предназначенная в первую очередь для обработки арифметических операций, выполняемых целевым процессором. не может действовать напрямую. [53]
GCC использует в своей сборке множество дополнительных инструментов, многие из которых по умолчанию установлены во многих дистрибутивах Unix и Linux (но обычно отсутствуют в установках Windows), включая Perl , [ необходимо дальнейшее объяснение ] Flex , Bison и другие распространенные инструменты. Кроме того, в настоящее время для сборки требуется наличие трех дополнительных библиотек: GMP , MPC и MPFR . [54]
В мае 2010 года руководящий комитет GCC решил разрешить использование компилятора C++ для компиляции GCC. [55] Компилятор должен был быть написан в основном на языке C плюс некоторые возможности C++. В частности, это было решено для того, чтобы разработчики GCC могли использовать деструкторы и обобщенные функции C++. [56]
В августе 2012 года руководящий комитет GCC объявил, что GCC теперь использует C++ в качестве языка реализации. [57] Это означает, что для сборки GCC из исходных кодов требуется компилятор C++, который понимает стандарт ISO/IEC C++03 .
18 мая 2020 года GCC перешел от стандарта ISO/IEC C++03 к стандарту ISO/IEC C++11 (т.е. необходим для компиляции, начальной загрузки самого компилятора; однако по умолчанию он компилирует более поздние версии C++). [58]
Каждый внешний интерфейс использует синтаксический анализатор для создания абстрактного синтаксического дерева данного исходного файла . Благодаря абстракции синтаксического дерева исходные файлы любого из поддерживаемых языков могут обрабатываться одной и той же серверной частью . GCC начал использовать парсеры LALR , созданные с помощью Bison , но постепенно перешёл на рукописные парсеры рекурсивного спуска для C++ в 2004 году, [59] и для C и Objective-C в 2006 году. [60] По состоянию на 2021 год все внешние интерфейсы используют ручной -написанные парсеры с рекурсивным спуском.
До GCC 4.0 древовидное представление программы не было полностью независимым от целевого процессора. Значение дерева несколько различалось для разных языковых интерфейсов, и внешние интерфейсы могли предоставлять свои собственные древовидные коды. Это было упрощено с появлением GENERIC и GIMPLE, двух новых форм языково-независимых деревьев, которые были представлены с появлением GCC 4.0. GENERIC более сложен и основан на промежуточном представлении интерфейса Java GCC 3.x. GIMPLE — это упрощенный GENERIC, в котором различные конструкции опускаются до нескольких инструкций GIMPLE. Интерфейсы C , C++ и Java создают GENERIC непосредственно во интерфейсе. Другие интерфейсы вместо этого имеют разные промежуточные представления после анализа и преобразуют их в GENERIC.
В любом случае так называемый «гимплификатор» затем преобразует эту более сложную форму в более простую форму GIMPLE на основе SSA , которая является общим языком для большого количества мощных глобальных (областей функций) оптимизаций, независимых от языка и архитектуры.
GENERIC — это промежуточный язык представления , используемый в качестве «среднего конца» при компиляции исходного кода в исполняемые двоичные файлы . Подмножество, называемое GIMPLE , предназначено для всех внешних интерфейсов GCC.
Средний этап GCC выполняет весь анализ и оптимизацию кода , работая независимо как от компилируемого языка, так и от целевой архитектуры, начиная с представления GENERIC [61] и расширяя его до языка передачи регистров (RTL). Представление GENERIC содержит только подмножество императивных программных конструкций, оптимизированных средним концом.
При преобразовании исходного кода в GIMPLE [62] сложные выражения разбиваются на трехадресный код с использованием временных переменных . Это представление было вдохновлено представлением SIMPLE, предложенным в компиляторе McCAT [63] Лори Дж. Хендрен [64] для упрощения анализа и оптимизации императивных программ .
Оптимизация может происходить на любом этапе компиляции; однако основная часть оптимизации выполняется после синтаксического и семантического анализа внешнего интерфейса и перед генерацией кода внутреннего интерфейса; таким образом, общее, хотя и несколько противоречивое, название этой части компилятора — «средний конец».
Точный набор оптимизаций GCC варьируется от выпуска к выпуску по мере его разработки, но включает в себя стандартные алгоритмы, такие как оптимизация цикла , переход к потокам , исключение общих подвыражений , планирование инструкций и т. д. Оптимизации RTL имеют меньшее значение с добавлением глобальных оптимизаций на основе SSA для деревьев GIMPLE [65] , поскольку оптимизации RTL имеют гораздо более ограниченную область применения и содержат меньше информации высокого уровня.
Некоторые из этих оптимизаций, выполняемых на этом уровне, включают устранение мертвого кода , устранение частичной избыточности , глобальную нумерацию значений , разреженное условное распространение констант и скалярную замену агрегатов. Также выполняются оптимизации на основе зависимости массива, такие как автоматическая векторизация и автоматическое распараллеливание . Также возможна оптимизация на основе профиля . [66]
Проект GCC включает в себя реализацию стандартной библиотеки C++ под названием libstdc++, [67] лицензированную по лицензии GPLv3, за исключением возможности связывания приложений, не использующих GPL, когда исходные тексты собираются с помощью GCC. [68]
Некоторые особенности GCC включают в себя:
-fgnu-tm
. [8] [73]typeof
выражения. [77]Основными поддерживаемыми (и наиболее протестированными) семействами процессоров являются 64- и 32-битные ARM, 64- и 32-битные x86_64 и x86 , а также 64-битные PowerPC и SPARC . [78]
Семейства целевых процессоров GCC начиная с версии 11.1 включают: [79]
Менее известные целевые процессоры, поддерживаемые в стандартной версии, включают:
Дополнительные процессоры поддерживаются версиями GCC, поддерживаемыми отдельно от версии FSF:
Компилятор Java GCJ может работать как с собственной архитектурой машинного языка, так и с байт-кодом Java виртуальной машины Java . [82] При перенацеливании GCC на новую платформу часто используется начальная загрузка . Motorola 68000, Zilog Z80 и другие процессоры также используются в версиях GCC, разработанных для различных программируемых графических калькуляторов Texas Instruments, Hewlett Packard, Sharp и Casio. [83]
GCC лицензируется в соответствии с Генеральной общественной лицензией GNU версии 3. [84] Исключение времени выполнения GCC разрешает компиляцию проприетарных программ (в дополнение к бесплатному программному обеспечению) с помощью GCC. Это не влияет на условия лицензии исходного кода GCC. [85]
Поэтому он написал автору VUCK, спрашивая, может ли GNU его использовать. Очевидно, разработчик VUCK отказался сотрудничать, ответив, что университет бесплатный, а компилятор — нет.
GCC был портирован (т.е. модифицирован для работы) на более чем 60 платформ, что больше, чем у любого другого компилятора.
{{cite web}}
: CS1 maint: bot: исходный статус URL неизвестен ( ссылка )