ЦП с адресуемыми файлами GPR, адресом регистровых переменных и псевдонимом между памятью и регистрами

Фон

Некоторые процессоры, такие как Atmel AVR, иметь регистровый файл общего назначения, который также является частью основной памяти — см. рис. 7-2 в разделе 7.4 и абзац после фигура.

О чем думала WG14?

Учитывая это, почему комитет C решил сделать

register int ri;
int* pi = &ri;

повсеместно неправильно сформирован, согласно сноске 101 к N1124 раздел 6.7.1? Не будет ли неопределенное или определяемое реализацией поведение более разумным, учитывая, что приведенный выше код имеет смысл по крайней мере на одном процессоре, а C изгибается назад, чтобы приспособиться к гораздо более странным (и более редким!) целям, чем AVR?

101) Реализация может рассматривать любое объявление register просто как объявление auto. Однако независимо от того, используется ли на самом деле адресуемое хранилище, адрес любой части объекта, объявленного с помощью спецификатора класса хранения register, не может быть вычислен ни явно (путем использования унарного оператора &, как обсуждалось в 6.5.3.2), ни неявно ( путем преобразования имени массива в указатель, как обсуждалось в 6.3.2.1). Таким образом, единственный оператор, который можно применить к массиву, объявленному со спецификатором класса хранения register, — это sizeof.

Я просто изменил регистр ЦП через указатель. Wat?!

Кроме того, используя расширение явных регистровых переменных GCC, можно указать компилятору поместить переменную в определенный регистр. В этом случае вы можете получить указатель с псевдонимом регистровой переменной, как показано ниже:

register int ri asm("r15") = 0;
int* pi = (int*)0x15;
/* pi now aliases ri */
*pi = 42;
/* ri is 42 now */
assert(ri == 42);

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


person LThode    schedule 13.11.2014    source источник
comment
Каково будет использование/значение вашего первого примера фрагмента (т.е. взятие адреса неспецифического регистра)?   -  person Oliver Charlesworth    schedule 13.11.2014
comment
В первом фрагменте pi будет установлен на адрес памяти регистра — на AVR это то же самое, что и номер регистра. Что касается его использования? Одной из возможностей было бы сохранить важную переменную для быстрого доступа в сложном внутреннем цикле, но при этом позволить подпрограммам этого внутреннего цикла изменять ее (как если бы она была закрыта).   -  person LThode    schedule 13.11.2014
comment
Вопрос, который вы должны задать, заключается в том, почему ваш GCC не реализует это как расширение. По умолчанию GCC не соответствует ни одному стандарту, поэтому не требуется рассматривать ваш первый пример как ошибку. (Даже при строгом соблюдении большинство GCC требуется только для выдачи диагностики, он все равно может принять ваш пример с предупреждением о том, что он не соответствует требованиям.)   -  person Ross Ridge    schedule 14.11.2014
comment
@RossRidge: Похоже, я должен отправить запрос функции команде GCC ... будет ли Bugzilla подходящим местом для этого?   -  person LThode    schedule 14.11.2014
comment
Возможно, но вам нужно будет гораздо лучше обосновать, почему это было бы полезно. Вам нужно будет показать убедительные примеры исходного кода, которые невозможно реализовать каким-либо другим способом с использованием существующих функций компилятора. Компилятор, который уже реализует это, был бы хорош. Я не уверен, где правильно делать формальный запрос на улучшение, но сначала обсудить его в списке рассылки GCC может быть хорошей идеей.   -  person Ross Ridge    schedule 14.11.2014


Ответы (1)


C — это абстрактный язык, определенный без знания машины, которая в конечном итоге будет его реализовывать. Определение C не предполагает, что базовая машина будет даже иметь регистры в обычном виде (или стек, или непрерывную память, или много других вещей, не имеющих отношения к этому вопросу, которые присутствуют на реальных машинах) .

Дело в том, что register не означает, что переменной должен быть присвоен машинный регистр. значение ключевого слова заключается в том, что у переменной не может быть взят адрес; тогда компилятор теоретически может выполнить лучшую оптимизацию, потому что он уменьшает количество путей, по которым переменная потенциально может быть изменена. Получение адреса переменной register не имеет смысла в C, независимо от того, на каком процессоре она работает, потому что register — это ключевое слово с невероятно неудачным названием (названное в честь наиболее очевидной оптимизации, которую оно обеспечивает), которое в частности значит адрес брать не надо. Это все, что это значит.

Интеллектуальный компилятор для AVR должен быть в состоянии сделать эту оптимизацию без вашего намека на это, в любом случае (на практике ключевое слово бесполезно именно потому, что любой полуприличный компилятор может определить, когда оно будет применимо в любом случае, поскольку в принципе нет четко определенных способ сослаться на объект auto без явного указания его адреса).

person Leushenko    schedule 13.11.2014
comment
Хотя это хорошее объяснение текущего состояния стандарта C, оно не проливает света на то, как WG14 пришла к такому определению. - person LThode; 13.11.2014
comment
Я чувствую, что вы просите объяснить, как register в конечном итоге получил это значение... то есть рассуждаете в обратном направлении: сначала появилось значение, а затем к нему было добавлено неточное имя. Альтернатива — сделать ее определяемой реализацией — на самом деле не кажется более полезной, чем позволить компилятору добавить дополнительные функции, такие как asm выше. - person Leushenko; 13.11.2014