2018年09月12日

clangのarm-eabiターゲットはenumが固定長

ARM の AAPCS の仕様では、enum のサイズは可変長と固定長の 2 パターン許されています。

異なるバイナリをリンクすると当然、正常動作は期待できないため、これは重要な違いとなります。


どちらに決まるかはプラットフォーム ABI 依存で、ベアメタル(arm-eabi ターゲット)では aapcs、Linux(arm-gnueabi(hf) ターゲット)では aapcs-linux がデフォルトで使用されます。

どちらも正確な資料がちょっと見つからなかったのですが、aapcs は可変長 enum で、実際 GCC と ARMCC はそうなっています。aapcs-linux は、基本的には aapcs で、enum が 4 バイト固定長である点が異なるようです。
http://kanj.github.io/elfs/book/armMusl/cross-tools/abi.html

推測ですが、ベアメタルはメモリが限られているため、このような仕様になっていると思われます。

一方 clang は、arm-eabi を指定した場合でも、enum は 4 バイト固定長となります。(4.0.0 と 6.0.0 で確認。)

clang 6.0.0 の lib/Basic/Targets/ARM.cpp に以下のようなコメントがあるので、これは将来的には修正されるのかもしれません。(これは現時点での HEAD でも同じで、aapcs、aapcs-vfp、aapcs-linux は全部同じ挙動になるようです。)
  // FIXME: Enumerated types are variable width in straight AAPCS.
eabi を指定した場合、ベアメタルでは aapcs を指定したことになるので、これは期待した挙動と異なりますし、実際 Clang の arm-eabi でビルドしたバイナリは GCC の arm-eabi でビルドしたライブラリとリンクしようとすると、以下のような警告が出ます。
uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail 
Clang に -fshort-enums オプションを付ければ問題は無いのですが、なぜ修正されないのでしょうかね。Linux と iOS 以外の ARM ベアメタル環境で Clang はあまり使われていないからでしょうか?

ちなみに弊社の SOLID は、基本は最適化や実績に一日の長がある GCC でビルドし、解析機能を使いたい場合は Clang でもビルドできるという両対応仕様(標準ライブラリは GCC のものを使用)なので、GCC に -fno-short-enums オプションを付けて、固定長 enum 設定でライブラリをビルドし、Clang との相互運用を実現しています。(ツールチェーンのバージョン s002 以降。)
どちらに合わせても良いので、当初は GCC と aapcs 仕様への準拠を中心に考え可変長 enum でしたが、様々なユーザ様の要望や、比較的メモリリッチな環境を対象としていることなどから総合的に判断し、s002 からはわかりやすく互換性が高い 4 バイト固定長を採用しました。

kmckk at 14:18コメント(0)ARM | 若槻 

コメントする

名前
URL
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード