# HG changeset patch # User Takahiro SHIMIZU # Date 1547132478 -32400 # Node ID 1f9baa69dfe085115d777a398f13575faa62dcb6 # Parent 2818fc986f3b23cb3e66381653e23349927b6479 update diff -r 2818fc986f3b -r 1f9baa69dfe0 Slide/slide.html --- a/Slide/slide.html Thu Jan 10 21:57:54 2019 +0900 +++ b/Slide/slide.html Fri Jan 11 00:01:18 2019 +0900 @@ -93,11 +93,13 @@

研究目的

@@ -107,21 +109,21 @@

Continuation Based C (CbC)

-
extern int printf(const char*,...);
-  int main (){
-     int data = 0;
-     goto cg1(&data);
+
+int main (){
+    int data = 0;
+    goto cg1(&data);
 }
 __code cg1(int *datap){
-      (*datap)++;
+    (*datap)++;
     goto cg2(datap);
 }
 __code cg2(int *datap){
@@ -173,10 +175,7 @@
 
  • Rakudoとは現在のPerl6の主力な実装である.
  • 実行環境のVM, Perl6のサブセットであるNQP(NotQuitPerl), NQPで記述されたPerl6(Rakudo)という構成になっている.
  • -
  • - コンパイラは, NQPで記述されたPerl6コンパイラ, NQPで記述されたNQPコンパイラ, MoarVMバイトコードを解釈するMoarVMという構成である -
  • -
  • 現在はMoarVMがRakudoの中でも主流なVM実装となっている.
  • +
  • コンパイラは, NQPで記述されたPerl6コンパイラ, NQPで記述されたNQPコンパイラ, MoarVMバイトコードを解釈するMoarVMという構成である
@@ -190,7 +189,7 @@
  • Perl6専用のVMであり, Cで記述されている
  • レジスタマシンとして実装されている.
  • -
  • MoarVMはバイトコードインタプリタを src/core/interp.c で定義しており, この中の関数 MVM_interp_run で命令に応じた処理を実行する
  • +
  • MoarVMはバイトコードインタプリタを src/core/interp.c で定義しており, この中の関数 MVM_interp_run でバイトコードに応じた処理を実行する
@@ -303,16 +302,11 @@
  • このテーブルはcbc_nextというCodeGearから参照し, 以降はこのCodeGearの遷移として処理が継続される.
  • -
    #define NEXT_OP(i) (i->op = *(MVMuint16 *)(i
    -    ->cur_op), i->cur_op += 2, i->op)
    +
    #define NEXT_OP(i) (i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op)
     #define DISPATCH(op) {goto (CODES[op])(i);}
     #define OP(name) OP_ ## name
     #define NEXT(i) CODES[NEXT_OP(i)](i)
     static int tracing_enabled = 0;
    -
    -_code cbc_next(INTERP i){
    -    goto NEXT(i);
    -}
     
    __code (* CODES[])(INTERP) = {
    @@ -371,46 +365,23 @@
       
  • OP(.*)(.*)の部分をCodeGearの名前として先頭に cbc_ をつけた上で設定する.
  • cur_opなどはINTERPを経由してアクセスする様に修正する.
  • 末尾の NEXT を次のCodeGearにアクセスする為に cbc_next に修正する.
  • -
  • case文で次のcase文に流れる箇所は, 直接その下のcase文に該当するCodeGearに遷移する.
  • -
  • GC対策の為に, CodeGear中のローカル変数をグローバル変数の配列に保存している箇所は,CodeGearに直接処理を書かず, CodeGearから別の関数を呼び出す形に修正する -
      -
    • その際に, 保存するローカル変数をstatic変数に修正するなどの工夫を行う
    • -
    -
  • -
    __code cbc_no_op(INTERP i){
    -    goto cbc_next(i);
    -}
    -__code cbc_const_i8(INTERP i){
    -    goto cbc_const_i16(i);
    +
    
    +__code cbc_next(INTERP i){
    +    __code (*c)(INTERP);
    +    c = CODES[(i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op)]; // c = NEXT(i)
    +    goto c(i);
     }
    -__code cbc_const_i16(INTERP i){
    -    goto cbc_const_i32(i);
    +_code cbc_next(INTERP i){
    +    goto NEXT(i);
     }
    -__code cbc_const_i32(INTERP i){
    -    MVM_exception_throw_adhoc(i->tc, "const_iX NYI");
    -   goto cbc_const_i64(i);
    -}
    +
     __code cbc_const_i64(INTERP i){
         GET_REG(i->cur_op, 0,i).i64 = MVM_BC_get_I64(i->cur_op, 2);
         i->cur_op += 10;
         goto cbc_next(i);
     }
    -__code cbc_pushcompsc(INTERP i){
    -    MVMObject * sc;
    -    sc  = GET_REG(i->cur_op, 0,i).o;
    -    if (REPR(sc)->ID != MVM_REPR_ID_SCRef)
    -        MVM_exception_throw_adhoc(i->tc, "Can only push an SCRef with pushcompsc");
    -    if (MVM_is_null(i->tc, i->tc->compiling_scs)) {
    -        MVMROOT(i->tc, sc, {
    -            i->tc->compiling_scs = MVM_repr_alloc_init(i->tc, i->tc->instance->boot_types.BOOTArray);
    -        });
    -    }
    -    MVM_repr_unshift_o(i->tc, i->tc->compiling_scs, sc);
    -    i->cur_op += 2;
    -    goto cbc_next(i);
    -}
     
    @@ -449,6 +420,41 @@
    +

    NQPのバイトコード

    + +
      +
    • NQPはMoarVMのバイトコードにコンパイルし, バイトコードをファイルに保存することが可能である
    • +
    • MoarVMのバイトコードは, アセンブリの様にダンプする事が可能である
    • +
    • 実際に先程のコードをバイトコードにコンパイルし, 対応するバイトコードをダンプすると次の様に表示される
    • +
    + +
         annotation: hoge.nqp:3
    +     label_1:
    +00007      const_i64_16       loc_2_int, 1
    +00008      gt_i               loc_2_int, loc_0_int, loc_2_int
    +00009      unless_i           loc_2_int, label_2(00022)
    +00010      osrpoint
    +     annotation: hoge.nqp:4
    +00011      decont             loc_3_obj, loc_1_obj
    +00012      smrt_numify        loc_4_num, loc_3_obj
    +00013      coerce_ni          loc_5_int, loc_4_num
    +00014      add_i              loc_5_int, loc_5_int, loc_0_int
    +00015      hllboxtype_i       loc_3_obj
    +00016      box_i              loc_3_obj, loc_5_int, loc_3_obj
    +00017      set                loc_1_obj, loc_3_obj
    +     annotation: hoge.nqp:5
    +00018      const_i64_16       loc_5_int, 1
    +00019      sub_i              loc_5_int, loc_0_int, loc_5_int
    +00020      set                loc_0_int, loc_5_int
    +00021      goto               label_1(00007)
    +
    + + + +
    + +
    +

    MoarVMのデバッグ手法

      @@ -590,6 +596,7 @@
    +
    @@ -599,8 +606,15 @@
    • 現在はNQP, Rakudoのセルフビルドが達成でき, オリジナルと同等のテスト達成率を持っている
    • moarの起動時のオプションとして --cbc を与えることによりCbCで動き, そうでない場合は通常のCで記述された箇所で実行される
    • +
    • Perl6の実行バイナリperl6, NQPの実行バイナリnqp は, それぞれmoarを起動するシェルスクリプトである為, --cbc オプションをシェルスクリプト内に書き加えることで, Perl6, NQPがそれぞれCbCで起動する
    +
    #!/bin/sh
    +exec /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/bin/moar --cbc \
    +     --libpath=/mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib \
    +     /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib/nqp.moarvm "$@"
    +
    +
    diff -r 2818fc986f3b -r 1f9baa69dfe0 Slide/slide.md --- a/Slide/slide.md Thu Jan 10 21:57:54 2019 +0900 +++ b/Slide/slide.md Fri Jan 11 00:01:18 2019 +0900 @@ -6,27 +6,29 @@ ## 研究目的 -- スクリプト言語であるPerl5の後継言語としてPerl6が現在開発されている. -- 現在主流なPerl6の実装にRakudoがあり, RakudoはNQP(Perl6のサブセット)で記述されたPerl6, NQPで記述されたNQPコンパイラがある -- NQPコンパイラはRakudoのVMであるMoarVM用のバイトコードを生成し, MoarVMはこのバイトコードを解釈, 実行する -- Continuation based C (CbC)という言語は継続を基本とするC言語であり, 言語処理系に応用出来ると考えられる -- CbC一部用いてMoarVMの書き換えを行い, 処理を検討する. +- 現在開発されているPerl6の実装にRakudoがあり, RakudoはNQP(Perl6のサブセット)で記述されたPerl6, NQPで記述されたNQPコンパイラ, NQPを解釈するVMで構成されている +- NQPコンパイラはRakudoのVMであるMoarVM用のバイトコードを生成し, MoarVMはこのバイトコードを解釈, 実行する +- Continuation based C (CbC)という言語は継続を基本とするC言語であり, 言語処理系に応用出来ると考えられる +- スクリプ言語などは, バイトコードを扱うが, この実行にcae文や, ラベルgotoなどを利用しており, この部分はCbCの機能で書き換える事が可能である +- 従って, CbC一部用いてPerl6にC処理系であるMoarVMの書き換えを行い, 処理を検討する. +![](fig/perl6nqp.svg) +- (Rakudoの構成図) ## Continuation Based C (CbC) - - Continuation Based C (CbC) はCodeGearを単位として用いたプログラミング言語である. - CodeGearはCの通常の関数呼び出しとは異なり,スタックに値を積まず, 次のCodeGearにgoto文によって遷移する. -- このgoto文による遷移を軽量継続と呼ぶ. - CodeGearはCの関数宣言の型名の代わりに`__code`と書く事で宣言出来る. +- CodeGearの引数は, 各CodeGearの入出力として利用する. ``` extern int printf(const char*,...); - int main (){ - int data = 0; - goto cg1(&data); + +int main (){ + int data = 0; + goto cg1(&data); } __code cg1(int *datap){ - (*datap)++; + (*datap)++; goto cg2(datap); } __code cg2(int *datap){ @@ -54,13 +56,12 @@ - 実行環境のVM, Perl6のサブセットであるNQP(NotQuitPerl), NQPで記述されたPerl6(Rakudo)という構成になっている. - コンパイラは, NQPで記述されたPerl6コンパイラ, NQPで記述されたNQPコンパイラ, MoarVMバイトコードを解釈するMoarVMという構成である -- 現在はMoarVMがRakudoの中でも主流なVM実装となっている. ## MoarVM - Perl6専用のVMであり, Cで記述されている - レジスタマシンとして実装されている. -- MoarVMはバイトコードインタプリタを `src/core/interp.c` で定義しており, この中の関数 `MVM_interp_run` で命令に応じた処理を実行する +- MoarVMはバイトコードインタプリタを `src/core/interp.c` で定義しており, この中の関数 `MVM_interp_run` でバイトコードに応じた処理を実行する ## MVM_interp_run @@ -137,16 +138,11 @@ - このテーブルは`cbc_next`というCodeGearから参照し, 以降はこのCodeGearの遷移として処理が継続される. ``` -#define NEXT_OP(i) (i->op = *(MVMuint16 *)(i - ->cur_op), i->cur_op += 2, i->op) +#define NEXT_OP(i) (i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op) #define DISPATCH(op) {goto (CODES[op])(i);} #define OP(name) OP_ ## name #define NEXT(i) CODES[NEXT_OP(i)](i) static int tracing_enabled = 0; - -_code cbc_next(INTERP i){ - goto NEXT(i); -} ``` ``` @@ -193,44 +189,24 @@ - `OP(.*)`の`(.*)`の部分をCodeGearの名前として先頭に `cbc_` をつけた上で設定する. - cur_opなどはINTERPを経由してアクセスする様に修正する. - 末尾の `NEXT` を次のCodeGearにアクセスする為に `cbc_next` に修正する. -- case文で次のcase文に流れる箇所は, 直接その下のcase文に該当するCodeGearに遷移する. -- GC対策の為に, CodeGear中のローカル変数をグローバル変数の配列に保存している箇所は,CodeGearに直接処理を書かず, CodeGearから別の関数を呼び出す形に修正する - - その際に, 保存するローカル変数をstatic変数に修正するなどの工夫を行う ``` -__code cbc_no_op(INTERP i){ - goto cbc_next(i); -} -__code cbc_const_i8(INTERP i){ - goto cbc_const_i16(i); + +__code cbc_next(INTERP i){ + __code (*c)(INTERP) + c = CODES[(i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op)]; // c = NEXT(i) + goto c(i); } -__code cbc_const_i16(INTERP i){ - goto cbc_const_i32(i); +_code cbc_next(INTERP i){ + goto NEXT(i); } -__code cbc_const_i32(INTERP i){ - MVM_exception_throw_adhoc(i->tc, "const_iX NYI"); - goto cbc_const_i64(i); -} + __code cbc_const_i64(INTERP i){ GET_REG(i->cur_op, 0,i).i64 = MVM_BC_get_I64(i->cur_op, 2); i->cur_op += 10; goto cbc_next(i); } -__code cbc_pushcompsc(INTERP i){ - MVMObject * sc; - sc = GET_REG(i->cur_op, 0,i).o; - if (REPR(sc)->ID != MVM_REPR_ID_SCRef) - MVM_exception_throw_adhoc(i->tc, "Can only push an SCRef with pushcompsc"); - if (MVM_is_null(i->tc, i->tc->compiling_scs)) { - MVMROOT(i->tc, sc, { - i->tc->compiling_scs = MVM_repr_alloc_init(i->tc, i->tc->instance->boot_types.BOOTArray); - }); - } - MVM_repr_unshift_o(i->tc, i->tc->compiling_scs, sc); - i->cur_op += 2; - goto cbc_next(i); -} ``` ## NQP @@ -253,6 +229,36 @@ say(add_test(10)); ``` +## NQPのバイトコード + +- NQPはMoarVMのバイトコードにコンパイルし, バイトコードをファイルに保存することが可能である +- MoarVMのバイトコードは, アセンブリの様にダンプする事が可能である +- 実際に先程のコードをバイトコードにコンパイルし, 対応するバイトコードをダンプすると次の様に表示される + + +``` + annotation: hoge.nqp:3 + label_1: +00007 const_i64_16 loc_2_int, 1 +00008 gt_i loc_2_int, loc_0_int, loc_2_int +00009 unless_i loc_2_int, label_2(00022) +00010 osrpoint + annotation: hoge.nqp:4 +00011 decont loc_3_obj, loc_1_obj +00012 smrt_numify loc_4_num, loc_3_obj +00013 coerce_ni loc_5_int, loc_4_num +00014 add_i loc_5_int, loc_5_int, loc_0_int +00015 hllboxtype_i loc_3_obj +00016 box_i loc_3_obj, loc_5_int, loc_3_obj +00017 set loc_1_obj, loc_3_obj + annotation: hoge.nqp:5 +00018 const_i64_16 loc_5_int, 1 +00019 sub_i loc_5_int, loc_0_int, loc_5_int +00020 set loc_0_int, loc_5_int +00021 goto label_1(00007) +``` + + ## MoarVMのデバッグ手法 - MoarVMはバイトコードをランダムに生成する仕様となっている @@ -360,10 +366,19 @@ 53 : 53 *54 : 8 ``` + ## 現在のCbCMoarVM - 現在はNQP, Rakudoのセルフビルドが達成でき, オリジナルと同等のテスト達成率を持っている - moarの起動時のオプションとして `--cbc` を与えることによりCbCで動き, そうでない場合は通常のCで記述された箇所で実行される +- Perl6の実行バイナリperl6, NQPの実行バイナリnqp は, それぞれmoarを起動するシェルスクリプトである為, `--cbc` オプションをシェルスクリプト内に書き加えることで, Perl6, NQPがそれぞれCbCで起動する + +``` +#!/bin/sh +exec /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/bin/moar --cbc \ + --libpath=/mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib \ + /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib/nqp.moarvm "$@" +``` ## CbCMoarVMの利点 diff -r 2818fc986f3b -r 1f9baa69dfe0 Slide/slide.pdf.html --- a/Slide/slide.pdf.html Thu Jan 10 21:57:54 2019 +0900 +++ b/Slide/slide.pdf.html Fri Jan 11 00:01:18 2019 +0900 @@ -77,11 +77,13 @@

    研究目的

    @@ -91,21 +93,21 @@

    Continuation Based C (CbC)

    -
    • Continuation Based C (CbC) はCodeGearを単位として用いたプログラミング言語である.
    • CodeGearはCの通常の関数呼び出しとは異なり,スタックに値を積まず, 次のCodeGearにgoto文によって遷移する.
    • -
    • このgoto文による遷移を軽量継続と呼ぶ.
    • CodeGearはCの関数宣言の型名の代わりに__codeと書く事で宣言出来る.
    • +
    • CodeGearの引数は, 各CodeGearの入出力として利用する.
    extern int printf(const char*,...);
    -  int main (){
    -     int data = 0;
    -     goto cg1(&data);
    +
    +int main (){
    +    int data = 0;
    +    goto cg1(&data);
     }
     __code cg1(int *datap){
    -      (*datap)++;
    +    (*datap)++;
         goto cg2(datap);
     }
     __code cg2(int *datap){
    @@ -157,10 +159,7 @@
     
    • Rakudoとは現在のPerl6の主力な実装である.
    • 実行環境のVM, Perl6のサブセットであるNQP(NotQuitPerl), NQPで記述されたPerl6(Rakudo)という構成になっている.
    • -
    • -

      コンパイラは, NQPで記述されたPerl6コンパイラ, NQPで記述されたNQPコンパイラ, MoarVMバイトコードを解釈するMoarVMという構成である

      -
    • -
    • 現在はMoarVMがRakudoの中でも主流なVM実装となっている.
    • +
    • コンパイラは, NQPで記述されたPerl6コンパイラ, NQPで記述されたNQPコンパイラ, MoarVMバイトコードを解釈するMoarVMという構成である
    @@ -174,7 +173,7 @@
    • Perl6専用のVMであり, Cで記述されている
    • レジスタマシンとして実装されている.
    • -
    • MoarVMはバイトコードインタプリタを src/core/interp.c で定義しており, この中の関数 MVM_interp_run で命令に応じた処理を実行する
    • +
    • MoarVMはバイトコードインタプリタを src/core/interp.c で定義しており, この中の関数 MVM_interp_run でバイトコードに応じた処理を実行する
    @@ -287,16 +286,11 @@
  • このテーブルはcbc_nextというCodeGearから参照し, 以降はこのCodeGearの遷移として処理が継続される.
  • -
    #define NEXT_OP(i) (i->op = *(MVMuint16 *)(i
    -    ->cur_op), i->cur_op += 2, i->op)
    +
    #define NEXT_OP(i) (i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op)
     #define DISPATCH(op) {goto (CODES[op])(i);}
     #define OP(name) OP_ ## name
     #define NEXT(i) CODES[NEXT_OP(i)](i)
     static int tracing_enabled = 0;
    -
    -_code cbc_next(INTERP i){
    -    goto NEXT(i);
    -}
     
    __code (* CODES[])(INTERP) = {
    @@ -355,46 +349,23 @@
       
  • OP(.*)(.*)の部分をCodeGearの名前として先頭に cbc_ をつけた上で設定する.
  • cur_opなどはINTERPを経由してアクセスする様に修正する.
  • 末尾の NEXT を次のCodeGearにアクセスする為に cbc_next に修正する.
  • -
  • case文で次のcase文に流れる箇所は, 直接その下のcase文に該当するCodeGearに遷移する.
  • -
  • GC対策の為に, CodeGear中のローカル変数をグローバル変数の配列に保存している箇所は,CodeGearに直接処理を書かず, CodeGearから別の関数を呼び出す形に修正する -
      -
    • その際に, 保存するローカル変数をstatic変数に修正するなどの工夫を行う
    • -
    -
  • -
    __code cbc_no_op(INTERP i){
    -    goto cbc_next(i);
    -}
    -__code cbc_const_i8(INTERP i){
    -    goto cbc_const_i16(i);
    +
    
    +__code cbc_next(INTERP i){
    +    __code (*c)(INTERP);
    +    c = CODES[(i->op = *(MVMuint16 *)(i->cur_op), i->cur_op += 2, i->op)]; // c = NEXT(i)
    +    goto c(i);
     }
    -__code cbc_const_i16(INTERP i){
    -    goto cbc_const_i32(i);
    +_code cbc_next(INTERP i){
    +    goto NEXT(i);
     }
    -__code cbc_const_i32(INTERP i){
    -    MVM_exception_throw_adhoc(i->tc, "const_iX NYI");
    -   goto cbc_const_i64(i);
    -}
    +
     __code cbc_const_i64(INTERP i){
         GET_REG(i->cur_op, 0,i).i64 = MVM_BC_get_I64(i->cur_op, 2);
         i->cur_op += 10;
         goto cbc_next(i);
     }
    -__code cbc_pushcompsc(INTERP i){
    -    MVMObject * sc;
    -    sc  = GET_REG(i->cur_op, 0,i).o;
    -    if (REPR(sc)->ID != MVM_REPR_ID_SCRef)
    -        MVM_exception_throw_adhoc(i->tc, "Can only push an SCRef with pushcompsc");
    -    if (MVM_is_null(i->tc, i->tc->compiling_scs)) {
    -        MVMROOT(i->tc, sc, {
    -            i->tc->compiling_scs = MVM_repr_alloc_init(i->tc, i->tc->instance->boot_types.BOOTArray);
    -        });
    -    }
    -    MVM_repr_unshift_o(i->tc, i->tc->compiling_scs, sc);
    -    i->cur_op += 2;
    -    goto cbc_next(i);
    -}
     
    @@ -433,6 +404,41 @@
    +

    NQPのバイトコード

    + +
      +
    • NQPはMoarVMのバイトコードにコンパイルし, バイトコードをファイルに保存することが可能である
    • +
    • MoarVMのバイトコードは, アセンブリの様にダンプする事が可能である
    • +
    • 実際に先程のコードをバイトコードにコンパイルし, 対応するバイトコードをダンプすると次の様に表示される
    • +
    + +
         annotation: hoge.nqp:3
    +     label_1:
    +00007      const_i64_16       loc_2_int, 1
    +00008      gt_i               loc_2_int, loc_0_int, loc_2_int
    +00009      unless_i           loc_2_int, label_2(00022)
    +00010      osrpoint
    +     annotation: hoge.nqp:4
    +00011      decont             loc_3_obj, loc_1_obj
    +00012      smrt_numify        loc_4_num, loc_3_obj
    +00013      coerce_ni          loc_5_int, loc_4_num
    +00014      add_i              loc_5_int, loc_5_int, loc_0_int
    +00015      hllboxtype_i       loc_3_obj
    +00016      box_i              loc_3_obj, loc_5_int, loc_3_obj
    +00017      set                loc_1_obj, loc_3_obj
    +     annotation: hoge.nqp:5
    +00018      const_i64_16       loc_5_int, 1
    +00019      sub_i              loc_5_int, loc_0_int, loc_5_int
    +00020      set                loc_0_int, loc_5_int
    +00021      goto               label_1(00007)
    +
    + + + +
    + +
    +

    MoarVMのデバッグ手法

      @@ -574,6 +580,7 @@
    +
    @@ -583,8 +590,15 @@
    • 現在はNQP, Rakudoのセルフビルドが達成でき, オリジナルと同等のテスト達成率を持っている
    • moarの起動時のオプションとして --cbc を与えることによりCbCで動き, そうでない場合は通常のCで記述された箇所で実行される
    • +
    • Perl6の実行バイナリperl6, NQPの実行バイナリnqp は, それぞれmoarを起動するシェルスクリプトである為, --cbc オプションをシェルスクリプト内に書き加えることで, Perl6, NQPがそれぞれCbCで起動する
    +
    #!/bin/sh
    +exec /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/bin/moar --cbc \
    +     --libpath=/mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib \
    +     /mnt/dalmore-home/one/src/Perl6/Optimize/llvm/build_perl6/share/nqp/lib/nqp.moarvm "$@"
    +
    +