LINUX.ORG.RU

Патченье GCC


0

0

Кто нибудь вносил правки в GCC? что рекоммендуете почитать? просто так открыв исходник сориентироваться по названиям тут не очень получается.

Не хватает одной возможности, ничего сложного в ней нет, решается дополнительным фильтром (можно на скриптах костыль сделать) между компилятором и ассемблером, но было бы лучше добавить возможность в GCC. Да и вообще инетерсно.

★★

Меня самого вопрос "что почитать" интересует. Но для твоего случая видимо самое то не патч, а gcc gem. http://www.ecsl.cs.sunysb.edu/gem/

Правда он только для жцц 4.1, так что его портировать надо.

Вообще-то есть и другие способы писать плагины, особенно для жцц 4.4 какая-то активность наблюдается.

www_linux_org_ru ★★★★★
()

Ну читать gcc internals и исходники. Еще была книжка по внутренностям gcc и даже намечался её перевод, но не видел, не читал.

Костыль на скриптах сделать будет точно много проще и быстрее. Gcc генерит ассемблерный листинг в самом конце процесса компиляции. На этом этапе уже нет очень много чего (что обычно хочется чтобы сделать "костыль"), т.е. доступен только минимум информации для генерации инструкций.

Напиши что нужно конкретно, может что посоветую.

ly
()
Ответ на: комментарий от ly

Надо сказать, что меня интересует только компилятор для AVR. И похоже я нашел место которое надо править, это две функции expand_prologue и expand_epilogue из файла gcc/config/avr/avr.c . Нужно добавить аттрибут функции, указывающий что для сохранения контекста надо использовать не стек, а указанную область памяти. Переменные на стеке можно запретить для таких функций, это только для обработчиков прерываний. Пример для понятности, вот что генерируется сейчас,

push r1
push r0
in r0, 0x3f
push r0
...
pop r0
out 0x3f, r0
pop r0
pop r1
reti

а надо чтобы,

sts addr, r1
sts addr-1, r0
in r0, 0x3f
sts addr-2, r0
...
lds r0, addr-2
out 0x3f, r0
lds r0, addr-1
lds r1, addr

Там на макросах что то лисп-подобное сооружено (как в Machine description), не очень понятно как переделать.

amaora ★★
() автор топика
Ответ на: комментарий от amaora

Если дело только в месте сохранения регистров, то это можно сделать, но не пойму зачем. Статическое хранение будет больше по размеру кода и больше по времени выполнения. IMHO проще и удобнее сделать так:

1) Объявляем функцию-обработчик с __attribute__((naked)), но gcc 4.1.x вывалиться на этом по ICE.

2) В самом начале через __asm ___volatile переключаемся на персональный стек с сохранением оригинального в static-переменной, не забываем про испорченные регистры (видимо r0 и r1).

3) Вызываем реальный обработчик, который может использовать переменные на стеке и делать все что угодно.

4) В конце naked-обработчика восстанавливаем стек и испорченные регистры.

Накладные расходы - один rcall и ret. При желании можно установить новый стек с запасом под локальные переменные и не переносить функционал обработчика в отдельную функцию (т.е. избавиться от rcall и ret).

ly
()
Ответ на: комментарий от ly

Это не больше по времени, sts/lds выполняются те же два такта что и push/pop, размер больше, но это маловажно.

Переключение на другой стек это лишняя задержка, 10+6 инструкций не считая rcall и ret, меньше не получается. Избавиться от rcall не выйдет, naked-функции не сохраняют используемые регистры, а как ещё можно обернуть функцию в свой пролог/эпилог?

А надо это для многозадачной ОС, чтобы не держать пустого места на всех стеках на случай прерывания.

amaora ★★
() автор топика
Ответ на: комментарий от amaora

Можно заставлять пользователя делать обработчик без переменных на стеке, но этот обработчик не должен вызывать другие функции ОС (они ведь будут использовать стек). Соответственно у меня возникает уверенность что такой обработчик возможен только в очень редких случаях.

Короче, думаю без переключения стека не обойтись. Даже в минимальной ОС должна быть возможность установить обработчик пользователя, который будет пробуждать (или еще как-нибудь) дергать другие задачи. Это значить что либо мы делаем "handmade" обработчик, и тогда можем делать то что вы хотите, либо должны обеспечить поддержку ABI (т.е. стек) для устанавливаемого пользователем обработчика.

Для примера, в http://code.google.com/p/uos-embedded/wiki/home_ru (используемая у нас версия ушла вперед, а руки до merge не доходят), с обработчиками дело обстоит так:

- ОС обеспечивает __weak обработчик для каждого прерывания. Этот обработчик может вызывать либо устанавливаемый fast-handler (с поддержкой ABI), либо дергать ассоциированный event (который ждут другие задачи);

- пользователь может заместить __weak-обработчик просто определив свой и делать в нем всё что захочет;

- отдельного стека для прерываний нет, т.е. используется стек задачи. Расходы на стеки нельзя назвать существенными, задач не так много (обычно 3-7).

ly
()
Ответ на: комментарий от ly

Тоесть такой возможности нет в GCC потому, что она не нужна, и не надо её туда добавлять?

Мне такая работа с прерываниями не нравится, лучше упрятать это в уровень драйверов, и работать с более высокими и простыми абстракциями.

amaora ★★
() автор топика
Ответ на: комментарий от amaora

Хотя, похоже я занимаюсь преждевременной оптимизацией. Надоело возится, сделаю грубо (naked и сохраниение всего контекста, т.к. оно все менее заметно на фоне разросшегося основного кода обработчика), если задержки будут не слишком большими, так и оставлю.

amaora ★★
() автор топика
Ответ на: комментарий от amaora

Похоже я не донес главную мысль:

- обработчик должен взаимодействовать с другими задачами в системе, например будить их. Если операционка не позволяет такого делать, то её применение сильно ограничено кучей проблем.

- чтобы обработчик мог будить задачи ему должно быть позволено вызывать часть функций ОС. Эти функции либо должны быть на общем ABI (использовать стек), либо иметь отдельные варианты для вызова из обработчика. Во втором случае можно обойтись без стека, но появляется масса возьни с отдельным набором функций.

- если прерывание прерывает низко-приоритетную задачу, а обработчик пробуждает задачу с более высоким приоритетом, то мало-мальски адекватная ОС должна сделать переключение контекста. Т.е. по выходу из обработчика должна выполняться другая задача.

- пробуждаемая задача имеет право уснуть (с учетом наследования приоритетов) в любой функции ОС. Стало быть переключение контекстов предполагает их однообразие для прерываний и не-прерываний.

В результате получается что в нормальной ОС не только проще, но и нужно переключать стек.

ly
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.