[R8C][M16C] #pragma ADDRESSの調査
NC30には、指定したアドレスにオブジェクトを配置するための#pragma ADDRESS指令があります。これは通常、SFRにアクセスするために用いるもので、*(volatile unsigned char*)0x0052 などと書くより便利です。また、1ビットのビットフィールドにアクセスする場合には、bset などのビット命令に展開されるという強みもあります。
今回、まず初めに調査したのは、CとC++に共通した内容として、#pragma ADDRESSで使用したオブジェクトを直接使用した場合は効率のよいコードが生成されるけれども、ポインタや(C++の場合は)参照を使って間接的にアクセスした場合はどうかということです。実際試してみた結果、間接的にアクセスした場合はビット命令は生成されず、通常のオブジェクトと同じように扱われることが分かりました。
次に調査したのは、C++で#pragma ADDRESS指令を使う場合、オブジェクト名の指定はどの程度のことができるのかということです。というのは、Cであればオブジェクト名は単純な識別子で必ず表現できますが、C++の場合は、名前空間やクラス名やテンプレート引数が絡んでくるからです。
実験してみたところ、名前空間やクラス名は問題なく指定することができました。ところが、クラステンプレートの場合、テンプレート実引数を指定して実体を特定しても、コンパイルすることができませんでした。例えば、以下のようにした場合、コンパイルエラー(C6677 (E) Invalid pragma declaration)になってしまいます。
struct A
{
static unsigned char a;
};
#pragma ADDRESS A<1>::a 0000H
template <int N>
unsigned char A<N>::a;
これはおそらくシンタックスが受け付けられないのだと思います。そこで、A<1>型にtypedef名を付けると、どうにかコンパイルを通すことができました。ところが、コンパイル結果を見てみると、単に#pragma ADDRESS指令が無視されているだけのようで、単なるオブジェクトと同じように振る舞っています。

