Является ли соглашение о вызовах компилятором или компоновщиком?

Когда мы помещаем _stdcall (вызывающему не нужно очищать стек) в прототип функции, заботится ли об этом компилятор или компоновщик?


person kern    schedule 05.05.2011    source источник


Ответы (3)


Соглашение о вызовах влияет на генерацию кода, поэтому этим занимается компилятор. Линкеру не нужно знать об этом.

person David Heffernan    schedule 05.05.2011
comment
Будем надеяться, что имена искажены по-другому, так что несоответствие в соглашении о вызовах вызовет ошибку во время компоновки. - person James Kanze; 05.05.2011
comment
@James Вам часто нужно указывать соглашения о вызовах при импорте DLL, и они обычно называются без искажений. - person David Heffernan; 05.05.2011
comment
Хеффеман Если функция extern "C", очевидно, соглашение о вызовах не может быть искажено в имени. Если функция extern "C++", нет причин, по которым она не может быть. - person James Kanze; 05.05.2011
comment
Импорт большинства dll @james отключает изменение, поэтому к dll можно получить доступ с помощью широкого спектра инструментов. - person David Heffernan; 05.05.2011

Соглашение о вызовах заключается в том, как вызывать функцию (конкретный машинный код для подготовки параметров и очистки ctack), а компоновщик определяет какую функцию (функцию, по какому адресу) вызывать.

Поэтому обычно компилятор генерирует правильный код и оставляет «заполнители» для точных адресов функций, а компоновщик затем помещает туда фактические адреса. При этом существует так называемая генерация кода во время компоновки, где оба делается компоновщиком.

person sharptooth    schedule 05.05.2011
comment
адрес функции не имеет ничего общего с соглашением о вызовах, тем не менее, соглашение о вызовах выполняется компилятором, верно? - person kern; 05.05.2011
comment
@kern: Да, если только не участвует LTCG. - person sharptooth; 05.05.2011

В некоторых системах объектный файл представляет собой просто набор данных, символов и точек исправления. Объектный файл сообщит компоновщику, что этот байт 574 связанного кода должен быть исправлен, чтобы содержать MSB разницы между символами Foo и Bar, и компоновщик сделает это, но компоновщик не имеет представления о значении, выходящем за пределы списка вычисления, которые необходимо выполнить.

В некоторых других системах компоновщик может гораздо больше заниматься генерацией кода. Например, некоторые процессоры ARM могут выполнять код, закодированный с использованием 16-битного или 32-битного набора инструкций. Некоторые типы кода могут эффективно работать только с использованием 32-битного набора инструкций; некоторые будут работать адекватно, но будут более компактными, используя 16-битный набор. Компоновщик ARM знает, какие подпрограммы написаны с использованием каждого набора инструкций, и если код, написанный с использованием одного набора инструкций, попытается вызвать функцию, написанную с использованием другого, компоновщик сгенерирует метод-оболочку, называемый «шпон», и вызовет первый вызов функции, который . Затем шпон выполнит операции, необходимые для вызова другого метода. Несмотря на то, что оболочка представляет собой «код», она полностью создается компоновщиком.

На самом деле нет фиксированного разделения труда между компиляторами и компоновщиками. Я видел некоторые системы, в которых «компилятор» переводит программу в «промежуточную» форму, а компоновщик выполняет всю реальную генерацию кода и проводит оптимизацию в зависимости от того, где что находится в памяти. Как уже отмечалось, есть и другие, в которых компоновщик представляет собой не что иное, как «обработчик исправлений». Вероятно, любое мыслимое разделение труда между этими крайностями существует где-то в какой-то системе.

person supercat    schedule 06.12.2013