2017-01-27 10 views
4

Я использую Clang как библиотеку для создания некоторых модулей LLVM IR.Как включить компиляцию встроенных функций в Clang?

Вот исходный код модуля:

inline int getSevenInline() { 
    return 7; 
} 

int getSeven() { 
    return getSevenInline(); 
} 

Я ожидал бы модуль LLVM IR содержит одну функцию, getSeven, которая возвращает 7.

Вот LLVM IR, который генерирует моя программа:

; ModuleID = './test.cpp' 
source_filename = "./test.cpp" 
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 
target triple = "x86_64-apple-macosx10.12.0" 

; Function Attrs: noinline ssp uwtable 
define i32 @_Z8getSevenv() #0 { 
entry: 
    %call = call i32 @_Z14getSevenInlinev() 
    ret i32 %call 
} 

declare i32 @_Z14getSevenInlinev() #1 

attributes #0 = { noinline ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } 
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } 

Когда я пытаюсь выполнить модуль, он не может разрешить символ для getSevenInline.

ИК Сомнительная двумя способами:

  1. функция getSevenInline не должна существовать, потому что она должна быть встраиваемыми
  2. Несмотря не встраиваются, getSevenInline не имеет реализации

Что следует ли настроить на моем clang::CompilerInstance так, чтобы он правильно компилировал функции inline?

У меня возникли проблемы с inline функциями; Функции, отличные от inline, работают правильно.


К сожалению, у меня слишком много коды, чтобы отправить всю программу, которая генерирует ИК, но я надеялся, что кто-то может мне точку к конфигурации для этого в исходном коде Clang.

+3

afaik, независимо от того, связан ли компилятор с функцией ключевого слова 'inline' – user463035818

ответ

1

мне удалось получить эту работу, но я не буду притворяться, я точно знаю, почему это работает:

for (auto declGroup : declGroups) { 
    codeGenerator->HandleTopLevelDecl(declGroup); 
} 

// For some reason this triggers the code generation for inline functions 
codeGenerator->HandleTranslationUnit(compilerInstance.getASTContext()); 

Я думаю речь идет о отсроченных decls; HandleTranslationUnit сообщает CodeGenerator, что он должен завершить компиляцию.

1

Спецификация C++ дает широту широты компилятора, чтобы решить, когда или когда не встроить функцию. Даже если вы явно объявляете функцию как встроенную, это все еще просто предложение относительно компилятора, и можно игнорировать это предложение, если оно решит, что полученный машинный код будет слишком раздутым или неэффективным. Это также сильно зависит от флажков оптимизации, которые вы передаете компилятору, и многих других зависимых от реализации деталей, которые полностью зависят от реализации компилятора.

C++ FAQ имеет некоторые подробности по этой теме:

Есть несколько способов, чтобы указать, что функция является рядный, некоторые из которых включают в инлайн ключевое слово, а другие нет. Независимо от того, как вы назначаете функцию как встроенную, это запрос, который компилятору можно игнорировать: компилятор может встроить-расширять некоторые, все или ни одно из мест, где вы вызываете функцию, обозначенную как встроенная. (Не разочаровывайтесь, если это кажется безнадежно неопределенным. Гибкость вышеизложенного на самом деле является огромным преимуществом: он позволяет компилятору рассматривать большие функции по-другому от небольших, а также позволяет компилятору генерировать код, который легко отлаживать, если вы выберете правильные параметры компилятора.)

что inline ключевого слова делает сделать, это гарантия того, что вы не получите несколько ошибок определения для функции с тем же именем.Например, если у вас есть (в myinlines.h):

inline int add(int a, int b) 
{ 
    return a + b; 
} 

и включить myinlines.h в file1.cpp и file2.cpp, вы не получите ошибки компоновщика при попытке связать вместе file1.o и file2.o в конечный исполняемый файл, даже если они оба содержат определение для int add(int, int). CPPReference имеет еще некоторые детали:

Там может быть более одного определения инлайн функции в программе до тех пор, как каждое определение появляется в другой единице трансляции и (для нестатических встроенных функций) все определения идентичны , Например, встроенная функция может быть определена в файле заголовка, который содержит # include'd в нескольких исходных файлах.

+0

Спасибо за фоновый рисунок, но на самом деле это не отвечает на мой вопрос. Кланг должен либо вставить функцию, либо не встроить ее, а добавить реализацию. В моем коде это не встраивание и не создание реализации. – sdgfsdh

+1

@sdgfsdh, справедливо. Я не эксперт по Клану, поэтому я буду откладывать на кого-то другого. –

 Смежные вопросы

  • Нет связанных вопросов^_^