CS+のコード生成ツールが生成するポインタ変数でvolatile修飾子の記述位置がおかしいものがあるように思います

藤田様の別スレッドに便乗なのですが、CS+のRL78のコード生成ツールが生成するuart通信機能のポインタ変数でvolatile修飾子の記述位置がおかしいものがあるように思います。具体的な変数名で言うと、gp_uart0_tx_addressとgp_uart0_rx_addressです。(CS+ for CC V5.00.00のコード生成機能で確認しました。)

コード生成ツールが生成した変数宣言は以下の通りです。

volatile uint8_t * gp_uart0_tx_address;         /* uart0 send buffer address */

volatile uint8_t * gp_uart0_rx_address;         /* uart0 receive buffer address */

ところが、以下の画面コピーの赤枠の箇所の通り、割り込みルーチン内で変更されるのはgp_uart0_tx_addressやgp_uart0_rx_addressの変数自身ですので以下の変数宣言が正しい気がします。

uint8_t * volatile gp_uart0_tx_address;         /* uart0 send buffer address */

uint8_t * volatile gp_uart0_rx_address;         /* uart0 receive buffer address */

試しに型修飾子の作用の仕方がvolatileと同様なconst(型修飾子の作用自体(機能)としては対義語的になる)で試してみると、変数自身に作用したのは以下の画面コピーのように橙枠の方でしたので、volatileも変数自身に作用させる場合には同様である筈です。

  • NoMaY様、ご指摘ありがとうございます。コード生成担当の鈴木です。
    開発部隊に伝えます!
  • >作用の仕方がvolatileと同様なconst(型修飾子の作用自体(機能)としては対義語的になる)で試してみると

     これって同様なんですか?鈴木さんも納得して回答しているみたいだし。
     本当に同様?
  • わわいです
    const は記述位置によってその作用はかわってきますが、
    volatileは記述位置にはよりませんね。
    どう書かれていようと、その変数に(関わる操作に)作用しますね
  • > volatileは記述位置にはよりませんね。

    いえ、拠りますが。

    $ cat -n hoge.c
         1  void hoge(void)
         2  {
         3      extern volatile int* hogehoge;
         4      while (*hogehoge) {
         5          ;
         6      }
         7      while (hogehoge) {
         8          ;
         9      }
        10  }
        11
        12  void piyo(void)
        13  {
        14      extern int* volatile piyopiyo;
        15      while (*piyopiyo) {
        16          ;
        17      }
        18      while (piyopiyo) {
        19          ;
        20      }
        21  }
    
    $ gcc -O2 -S hoge.c -o -
            .text
    hoge:
            movq    .refptr.hogehoge(%rip), %rax
            movq    (%rax), %rdx
    .L2:
            movl    (%rdx), %eax
            testl   %eax, %eax
            jne     .L2
    .L3:
            jmp     .L3
            .text
    piyo:
            movq    .refptr.piyopiyo(%rip), %rax
    .L7:
            movq    (%rax), %rdx
            movl    (%rdx), %edx
            testl   %edx, %edx
            jne     .L7
    .L9:
            movq    (%rax), %rdx
            testq   %rdx, %rdx
            jne     .L9
            ret
    $
    
  • 分けた方が良かったかな。

    $ cat -n piyo.c
         1  extern volatile int* hogehoge;
         2
         3  void hoge(void)
         4  {
         5      while (*hogehoge) {
         6          ;
         7      }
         8  }
         9
        10  void hogera(void)
        11  {
        12      while (hogehoge) {
        13          ;
        14      }
        15  }
        16
        17  extern int* volatile piyopiyo;
        18
        19  void piyo(void)
        20  {
        21      while (*piyopiyo) {
        22          ;
        23      }
        24  }
        25
        26  void piyora(void)
        27  {
        28      while (piyopiyo) {
        29          ;
        30      }
        31  }
    
    $ gcc -O2 piyo.c -S -o -
            .text
    hoge:
            movq    .refptr.hogehoge(%rip), %rax
            movq    (%rax), %rdx
    .L2:
            movl    (%rdx), %eax
            testl   %eax, %eax
            jne     .L2
            ret
    
            .text
    hogera:
            movq    .refptr.hogehoge(%rip), %rax
            movq    (%rax), %rax
    .L6:
            testq   %rax, %rax
            jne     .L6
            ret
    
            .text
    piyo:
            movq    .refptr.piyopiyo(%rip), %rdx
    .L9:
            movq    (%rdx), %rax
            movl    (%rax), %eax
            testl   %eax, %eax
            jne     .L9
            ret
    
            .text
    piyora:
            movq    .refptr.piyopiyo(%rip), %rdx
    .L12:
            movq    (%rdx), %rax
            testq   %rax, %rax
            jne     .L12
            ret
    
    $
    
  • 正直なところvolatileとconstの作用の仕方が同じだと理解するようになったのは、いつ、どこで、どの情報源から、(あるいは試行錯誤していた時にたまたま?、) だったのか思い出せなかったので、今回、(1)ANSI/ISO Cでは?、(2)CC-RLでは?、についてウェブ(Wikipedia+α)とCC-RLのヘルプで確認してみました。結果、作用の仕方が異なることを示唆する情報は見付からず、同じであることを示唆する「It(volatileを指す) can be used in exactly the same manner as const in declarations of variables, pointers, references, and member functions」という文言はWikipediaの「Type qualifier」の項に見付かり、またCC-RLでも同じであることを示唆する記述は見付かりました。

    (1)ANSI/ISO Cでの確認用に調べたウェブページ

    Type qualifier - Wikipedia
    Const - Wikipedia
    Volatile - Wikipedia
    const and volatile Pointers - Microsoft >...> C/C++ > Language and Standard Libraries > C++ Language Reference > Pointers
    const and volatile - ORACLE >...> Oracle Solaris Studio 12.3: C User's Guide > Transitioning to ISO C > 6.6

    (2)CC-RLでの確認用に調べたヘルプ項目

    __nearも__farもconstもvolatileもどれも作用対象(私の表現では作用の仕方)が同じと書かれている

  • fujita nozomu さん、コンパイル結果に疑問が有ります。
    ニーモニックの意味を全て把握しているわけじゃ無いけど、L3 に無条件でジャンプするのは何故?

    1 void hoge(void)
    2 {
    3 extern volatile int* hogehoge;
    4 while (*hogehoge) ;
    7 while (hogehoge) ;
    10 }

    hoge:
    movq .refptr.hogehoge(%rip), %rax
    movq (%rax), %rdx
    .L2: while (*hogehoge)に相当
    movl (%rdx), %eax
    testl %eax, %eax
    jne .L2
    .L3:              while (hogehoge)に相当
    jmp .L3       hogehoge がゼロでない事を何処で判断したの?
    .text
  • たぶん、これに絡んだ話ではないかと思います。(-fno-delete-null-pointer-checksを付けてコンパイル結果が変われば正にこの話だと思います。)

    KMC Staff Blog
    blog.kmckk.com/archives/1202810.html
    上記より引用

    GCC Manual 3.10 Options That Control Optimization -fdelete-null-pointer-checks
    マニュアルの説明を読むと、既に一回ポインタを間接参照した後の NULL チェックは無意味だから削除するという、何の問題も無い最適化に見えます。
    GCC 4.4.1 までは -O2,-O3,-Os で有効になっていたようですが、最新のマニュアルでは(一部のターゲットを除き)全ての最適化レベル(-O0 含む)で有効になると書いてあります。


    リカルドさんwrote: said:
    fujita nozomu さん、コンパイル結果に疑問が有ります。
    ニーモニックの意味を全て把握しているわけじゃ無いけど、L3 に無条件でジャンプするのは何故?
  • > L3 に無条件でジャンプするのは何故?

    NULL は何のオブジェクトも指しませんが、逆に、何かのオブジェクトを指すポインタは NULL でないことは確定的です。前段の hogehoge の指す先をアクセスした以降では hogehoge の値は NULL ではないということで、無限ループとなります。 

    $ cat -n hoge.c
         1  void hoge(void)
         2  {
         3      extern volatile int* hogehoge;
         4      while (*hogehoge) {
         5          ;
         6      }
         7      while (hogehoge) {
         8          ;
         9      }
        10  }
    
    $ gcc -O2 -S hoge.c -o -
            .text
    hoge:
            movq    .refptr.hogehoge(%rip), %rax
            movq    (%rax), %rdx
    .L2:
            movl    (%rdx), %eax
            testl   %eax, %eax
            jne     .L2
    .L3:
            jmp     .L3
    
  • わわいです
    いや、元質問のトピックにわざわざGCCもってこられましても。。