• Emscripten实现把C/C++文件转成wasm,wast(wasm的可读形式),llvm字节码(bc格式),ll格式(llvm字节码的可读形式)并执行wasm


    《一》˙转换

    Emscripten实现把C/C++文件转成wasm,wast(wasm的可读形式),llvm字节码(bc格式),ll格式(llvm字节码的可读形式)的步骤:

    最新版本的Emscripten(1.38.12)已经能实现把c/c++转成wasm文件,例子;

    (1)源文件:extern.cc  如果不加extern “c”{}则转出的wasm文件对应的wast文件只有module这个词。

    extern "C" {

    int add(int x, int y) {

      int a=333;

      return x + y+ a;

    }

    int min(int x, int y) {

      return x - y;

    }

    }

    (2)转成wasm命令:

    emcc extern.cc -o extern.js -s EXPORTED_FUNCTIONS='["_add","_min"]'  -O3

     注意:这里EXPORTED_FUNCTIONS指的是导出的函数,需要和源文件里的函数名是相对应的,-O3是编译优化等级,只有这个等级生成的wasm文件才会很小(几十字节),不加该优化选项,生成的wasm将会有几十KB。生成的时候会临时产生*.asm.js,等生成完后,会自动删掉。

    执行完将会生成 extern.js和extern.wasm两个文件。

     (3)转成wast可读文件:

       wasm2wat extern.wasm -o extern.wast

       wast文件内容:

       (module

      (type (;0;) (func (param i32 i32) (result i32)))

      (func (;0;) (type 0) (param i32 i32) (result i32)

        get_local 0

        get_local 1

        i32.sub)

      (func (;1;) (type 0) (param i32 i32) (result i32)

        get_local 0

        i32.const 333

        i32.add

        get_local 1

        i32.add)

      (export "_add" (func 1))

      (export "_min" (func 0)))

    (4)转成llvm字节码 bc格式:

     emcc extern.cc -o extern.bc -s EXPORTED_FUNCTIONS='["_add","_min"]'  -O3

    (5)使用llvm-dis把llvm字节码转成可读格式:

     llvm-dis extern.bc

     执行上述命令将生成extern.ll文件。

     extern.ll 文件内容:

    ; ModuleID = 'extern.bc'

    source_filename = "extern.cc"

    target datalayout = "e-p:32:32-i64:64-v128:32:128-n32-S128"

    target triple = "asmjs-unknown-emscripten"

    ; Function Attrs: norecurse nounwind readnone

    define i32 @add(i32, i32) local_unnamed_addr #0 {

      %3 = add i32 %0, 333

      %4 = add i32 %3, %1

      ret i32 %4

    }

    ; Function Attrs: norecurse nounwind readnone

    define i32 @min(i32, i32) local_unnamed_addr #0 {

      %3 = sub nsw i32 %0, %1

      ret i32 %3

    }

    attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

    !llvm.module.flags = !{!0}

    !llvm.ident = !{!1}

    !0 = !{i32 1, !"wchar_size", i32 4}

    !1 = !{!"clang version 6.0.1  (emscripten 1.38.12 : 1.38.12)"}

    最终生成的文件列表如下图:

     

    《二》执行

    Emscripten(1.38.12)执行把c/c++转成wasm文件的方法:

    方法一:用node执行

     源文件:extern-node.cc

    #include <stdio.h>

    #include <emscripten.h>

    extern "C"{

    void sayHi() {

      printf("Hi! ");

    }

    int daysInWeek() {

      return 7;

    }

    }

     编译命令:

     emcc -s EXPORTED_FUNCTIONS="['_sayHi', '_daysInWeek']" extern-node.cc -o extern-node.js

     编写node-test.js

     var em_module = require('./extern-node.js');

    em_module._sayHi();

    em_module.ccall("sayHi");

    console.log(em_module._daysInWeek());

     执行:

     Node node-test.js

    方法二:用web服务器执行

    源文件:extern.cc

    #include <emscripten.h>

    extern "C"{

      int gol=1111;

    int add(int x, int y) {

      int a= 333;

      //printf("hello world! %d ",a);

      return x + y+ a+gol;

    }

    int min(int x, int y) {

      return x - y;

    }

    }

    编译命令:

     emcc extern.cc  -s EXPORTED_FUNCTIONS="['_add']"  -o extern.js

     编写test.html

     <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

    <body>

    <h1>Test File</h1>

    <script type="text/javascript">

        var Module = {

          onRuntimeInitialized: function() {

            var a=Module._add(1,2); 

            document.write("result == " + a);

          }

        };

      </script>

    <script type="text/javascript" src="extern.js"></script>

    </body>

     在当前目录使用serve运行 serve -l 8000 (如果没有serve,则执行npm install -g serve)

     执行:在浏览器地址打开 localhost:8000/test

  • 相关阅读:
    个人博客08
    《新浪微博平台架构》---阅读
    《阿里游戏高可用架构设计实践》---阅读
    《京东咚咚架构演进》---阅读
    《京东话费充值系统架构演进实践》--阅读
    实时获取input框内容
    html:判断两次密码不一致以及阻止提交
    《京东到家库存系统架构设计》---阅读
    《数据蜂巢架构演进之路》---阅读
    SOA案例分析浅谈
  • 原文地址:https://www.cnblogs.com/405845829qq/p/10342374.html
Copyright © 2020-2023  润新知