FreeBSDでLLVM事始め

#はじめに
コンピュータというものに初めて接するビギナーが，FreeBSDを使いプログラミングを始める方を対象とします．

大学2回生がプログラミング実習（具体例として，以下の文献の「2章　Unix環境でのビギナープログラミング」）で学ぶ内容程度です．

* 池田克夫編：コンピュータサイエンス講座　情報工学実験，オーム社，1993年．

#環境
今回利用した環境は以下の通りです．
<dl>
  <dt>コンピュータ</dt>
  <dd>Raspberry Pi 2</dd>
  <dt>OS</dt>
  <dd>FreeBSD 12.2</dd>
</dl>

FreeBSDでは，LLVMコンパイラ基板をベースにしてプログラミングをします．
プログラミングは，エディタでソースプログラムを記述し，コンパイラによりオブジェクトプログラムに変換し，ライブラリとリンカにより結合して最終的な実行形式のプログラムを作成する作業です．

| 　　　 | ツール | バージョン |
|:-----------|:------------|:------------:|
| エディタ     | vi        |          |
| コンパイラ | Clang      | 10.0.1       |
| デバッガ     | LLDB       |        |
| リンカ      | LLD          | 10.0.1          |

LLVM ( [https://llvm.org](https://llvm.org) )に記載されているように，LLVMプロジェクトには，様々なライブラリも標準で利用できますが，今回は利用していません．

| 　　　 | ツール | バージョン |
|:-----------|:------------|:------------:|
| ライブラリ | LLVM Core        |          |
|  | libc++        |          |
|  | compiler-rt        |          |
|   | MLIR      |       |
|      | OpenMP      |        |
|      | polly      |        |
|      | livclc      |        |
|      | Klee      |        |

#Cプログラミング
参考文献の次の実習課題について，実際にプログラムを作成してみたいと思います．
>実習2．2
>英文のテキストファイルを読み込んで，その中の各アルファベットの数をカウント>し，ヒストグラムにして表示するプログラムを作成せよ．

引数にテキストファイルを入れて，ファイルポインタにより一文字ずつ読み込み文字のカウンタ配列にインクリメントしていく方法をとっています．

```c:myprog.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *fp;
    char *prog = argv[0];
    int c;
    int i,j;
    int nc[26];
    int hl;
    int ncmax;
    
    static int lower[26] = {
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
    };
    static int upper[26] = {
        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
    };

    for (i=0;i<26;i++)
        nc[i]=0;
    if (argc == 1) 
        exit(1);
    ncmax = 0;
    while(--argc > 0)
        if ((fp = fopen(*++argv, "r")) == NULL) {
            fprintf(stderr, "%s: can't open %s\n", prog, *argv);
            exit(1);
        } else {
            while ((c = getc(fp)) != EOF) {
                for (i=0;i<26;i++){
                    if ((c == lower[i]) | (c == upper[i])) nc[i]++;
                    if (ncmax < nc[i]) ncmax = nc[i];
                }
            }               
            hl  = ncmax / 60 ;
            for (i=0;i<26;i++){
                printf("%c:", lower[i]);
                for(j=0;j<(nc[i]/hl);j++)
                    printf("*");
                printf("\n");
            }
            fclose(fp);
        }
    exit(0);  
}

```

ccでコンパイルしてみます．
各オプションはマニュアルに記載されています．

```
freebsd@generic:~ % cc myprog.c -v
FreeBSD clang version 10.0.1 (git@github.com:llvm/llvm-project.git llvmorg-10.0.1-0-gef32c611aa2)
Target: armv7-unknown-freebsd12.2-gnueabihf
Thread model: posix
InstalledDir: /usr/bin
 "/usr/bin/cc" -cc1 -triple armv7-unknown-freebsd12.2-gnueabihf -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name myprog.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu generic -target-feature +strict-align -target-abi aapcs-linux -mfloat-abi hard -fallow-half-arguments-and-returns -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /usr/lib/clang/10.0.1 -fdebug-compilation-dir /home/freebsd -ferror-limit 19 -fmessage-length 80 -fno-signed-char -fgnuc-version=4.2.1 -fobjc-runtime=gnustep -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o /tmp/myprog-fe84db.o -x c myprog.c
clang -cc1 version 10.0.1 based upon LLVM 10.0.1 default target armv7-unknown-freebsd12.2-gnueabihf
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/clang/10.0.1/include
 /usr/include
End of search list.
 "/usr/bin/ld" --eh-frame-hdr -dynamic-linker /libexec/ld-elf.so.1 --hash-style=both --enable-new-dtags -o a.out /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /tmp/myprog-fe84db.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/crtend.o /usr/lib/crtn.o
```

最後に，シェークスピアの[ロミオとジュリエット](https://en.wikipedia.org/wiki/Romeo_and_Juliet)の文字数を読み込んでみました．qやx，zも実際は多数あるのですが，最も多いeから見ると少数のためヒストグラムに表示されない結果となりました．
ちなみに，実行時間は以下の通りでした．
0.367u 0.000s 0:00.36 100.0%	5+168k 0+0io 0pf+0w

```
freebsd@generic:~ % ./a.out romeo
a:***************************************
b:*******
c:***********
d:******************
e:************************************************************
f:**********
g:*********
h:******************************
i:********************************
j:*
k:***
l:**********************
m:***************
n:*******************************
o:*****************************************
p:********
q:
r:******************************
s:********************************
t:********************************************
u:*****************
v:*****
w:***********
x:
y:***********
z:
```

#最後に
clangのオプションについて，あまり調べきれていませんが，RaspberriPiのものは，gccベースのソースをコンパイルできるようにデフォルトオプションが設定されているのでしょうか．
LLVMのライブラリを使い，今後LLVMらしいプログラムなどにも触れていきたいと思います．