예제 #1
0
void CompiledExpression::generateSingleArgCall(X86Compiler& c, X86XmmVar& dest, X86XmmVar& arg, double (*function)(double)) {
    X86GpVar fn(c, kVarTypeIntPtr);
    c.mov(fn, imm_ptr((void*) function));
    X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder1<double, double>());
    call->setArg(0, arg);
    call->setRet(0, dest);
}
예제 #2
0
int main(int argc, char* argv[]) {
  using namespace asmjit;

  Performance perf;
  uint32_t kNumRepeats = 10;
  uint32_t kNumIterations = 10000;

  JitRuntime runtime;
  X86Assembler a(&runtime);
  X86Compiler c;

  uint32_t r, i;

  // --------------------------------------------------------------------------
  // [Bench - Opcode]
  // --------------------------------------------------------------------------

  perf.reset();
  for (r = 0; r < kNumRepeats; r++) {
    perf.start();
    for (i = 0; i < kNumIterations; i++) {
      asmgen::opcode(a);

      void *p = a.make();
      runtime.release(p);

      a.reset();
    }
    perf.end();
  }

  printf("Opcode   | Time: %-6u [ms] | Speed: %-9u [inst/s]\n",
    perf.best, instPerMs(perf.best, kNumIterations, asmgen::kGenOpCodeInstCount));

  // --------------------------------------------------------------------------
  // [Bench - Blend]
  // --------------------------------------------------------------------------

  perf.reset();
  for (r = 0; r < kNumRepeats; r++) {
    perf.start();
    for (i = 0; i < kNumIterations; i++) {
      c.attach(&a);
      asmgen::blend(c);
      c.finalize();

      void* p = a.make();
      runtime.release(p);
    }
    perf.end();
  }

  printf("Blend    | Time: %-6u [ms] | Speed: %-9u [inst/s]\n",
    perf.best, instPerMs(perf.best, kNumIterations, asmgen::kGenBlendInstCount));

  return 0;
}
예제 #3
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder1<int, int>());
    c.getFunc()->setHint(kFuncHintNaked, true);

    // Call a function.
    GpVar address(c.newGpVar());
    GpVar var(c.getGpArg(0));

    c.mov(address, imm((sysint_t)(void*)calledFunc));
    X86CompilerFuncCall* ctx;

    ctx = c.call(address);
    ctx->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder1<int, int>());
    ctx->setArgument(0, var);
    ctx->setReturn(var);

    ctx = c.call(address);
    ctx->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder1<int, int>());
    ctx->setArgument(0, var);
    ctx->setReturn(var);

    c.ret(var);
    c.endFunc();
  }
예제 #4
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder3<int, int, int, int>());

    GpVar v0(c.getGpArg(0));
    GpVar v1(c.getGpArg(1));
    GpVar v2(c.getGpArg(2));

    // Just do something;)
    c.shl(v0, imm(1));
    c.shl(v1, imm(1));
    c.shl(v2, imm(1));

    // Call function.
    GpVar address(c.newGpVar());
    c.mov(address, imm((sysint_t)(void*)calledFunc));

    X86CompilerFuncCall* fCall = c.call(address);
    fCall->setPrototype(kX86FuncConvDefault, FuncBuilder3<Void, int, int, int>());
    fCall->setArgument(0, v2);
    fCall->setArgument(1, v1);
    fCall->setArgument(2, v0);

    // TODO: FuncCall return value.
    // fCall->setReturn(v0);
    // c.ret(v0);

    c.endFunc();
  }
예제 #5
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder4<Void, int*, int, int, int>());

    GpVar dst0(c.getGpArg(0));
    GpVar v0(c.getGpArg(1));

    c.shl(v0, c.getGpArg(2));
    c.ror(v0, c.getGpArg(3));
    
    c.mov(dword_ptr(dst0), v0);
    c.endFunc();
  }
예제 #6
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder4<Void, int*, int*, int, int>());
    c.getFunc()->setHint(kFuncHintNaked, true);

    GpVar dst0_hi(c.getGpArg(0));
    GpVar dst0_lo(c.getGpArg(1));

    GpVar v0_hi(c.newGpVar(kX86VarTypeGpd));
    GpVar v0_lo(c.getGpArg(2));

    GpVar src0(c.getGpArg(3));
    c.imul(v0_hi, v0_lo, src0);

    c.mov(dword_ptr(dst0_hi), v0_hi);
    c.mov(dword_ptr(dst0_lo), v0_lo);
    c.endFunc();
  }
예제 #7
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder2<Void, int*, const int*>());
    c.getFunc()->setHint(kFuncHintNaked, true);

    GpVar dst = c.getGpArg(0);
    GpVar src = c.getGpArg(1);

    for (uint i = 0; i < 4; i++)
    {
      GpVar x = c.newGpVar(kX86VarTypeGpd);
      GpVar y = c.newGpVar(kX86VarTypeGpd);
      GpVar hi = c.newGpVar(kX86VarTypeGpd);

      c.mov(x, dword_ptr(src, 0));
      c.mov(y, dword_ptr(src, 4));

      c.imul(hi, x, y);
      c.add(dword_ptr(dst, 0), hi);
      c.add(dword_ptr(dst, 4), x);
    }

    c.endFunc();
  }
예제 #8
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder3<Void, int, int, char*>());
    c.getFunc()->setHint(kFuncHintNaked, true);

    GpVar src0(c.getGpArg(0));
    GpVar src1(c.getGpArg(1));
    GpVar dst0(c.getGpArg(2));

    c.cmp(src0, src1);
    c.setz(byte_ptr(dst0));

    c.endFunc();
  }
예제 #9
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder3<Void, void*, void*, size_t>());
    c.getFunc()->setHint(kFuncHintNaked, true);

    GpVar dst(c.getGpArg(0));
    GpVar src(c.getGpArg(1));
    GpVar cnt(c.getGpArg(2));

    c.rep_movsb(dst, src, cnt);
    c.endFunc();
  }
예제 #10
0
  virtual void compile(X86Compiler& c)
  {
    Label skip(c.newLabel());

    X86CompilerFuncDecl* func = c.newFunc(kX86FuncConvDefault, FuncBuilder1<int, int>());
    func->setHint(kFuncHintNaked, true);

    GpVar var(c.getGpArg(0));
    c.cmp(var, imm(1));
    c.jle(skip);

    GpVar tmp(c.newGpVar(kX86VarTypeInt32));
    c.mov(tmp, var);
    c.dec(tmp);

    X86CompilerFuncCall* fCall = c.call(func->getEntryLabel());
    fCall->setPrototype(kX86FuncConvDefault, FuncBuilder1<int, int>());
    fCall->setArgument(0, tmp);
    fCall->setReturn(tmp);
    c.mul(c.newGpVar(kX86VarTypeInt32), var, tmp);

    c.bind(skip);
    c.ret(var);
    c.endFunc();
  }
예제 #11
0
 virtual void compile(X86Compiler& c)
 {
   c.newFunc(kX86FuncConvDefault, FuncBuilder0<Void>());
   c.endFunc();
 }
예제 #12
0
  virtual void compile(X86Compiler& c)
  {
    int i;
    GpVar var[32];

    c.newFunc(kX86FuncConvDefault, FuncBuilder1<Void, int*>());

    for (i = 0; i < ASMJIT_ARRAY_SIZE(var); i++)
    {
      var[i] = c.newGpVar(kX86VarTypeGpd);
      c.xor_(var[i], var[i]);
    }

    GpVar v0(c.newGpVar(kX86VarTypeGpd));
    Label L(c.newLabel());

    c.mov(v0, imm(32));
    c.bind(L);

    for (i = 0; i < ASMJIT_ARRAY_SIZE(var); i++)
    {
      c.add(var[i], imm(i));
    }

    c.dec(v0);
    c.jnz(L);

    GpVar a0(c.getGpArg(0));
    for (i = 0; i < ASMJIT_ARRAY_SIZE(var); i++)
    {
      c.mov(dword_ptr(a0, i * 4), var[i]);
    }

    c.endFunc();
  }
예제 #13
0
void X86TestSuite::run()
{
  size_t i;
  size_t testCount = testList.getLength();

  for (i = 0; i < testCount; i++)
  {
    X86Compiler compiler;
    StringLogger logger;

    logger.setLogBinary(true);
    compiler.setLogger(&logger);

    X86Test* test = testList[i];
    test->compile(compiler);

    void *func = compiler.make();

    // In case that compilation fails uncomment this section to log immediately
    // after "compiler.make()".
    //
    // fprintf(stdout, "%s\n", logger.getString());
    // fflush(stdout);

    if (func != NULL)
    {
      StringBuilder output;
      StringBuilder expected;

      if (test->run(func, output, expected))
      {
        fprintf(stdout, "[Success] %s.\n", test->getName());
      }
      else
      {
        fprintf(stdout, "[Failure] %s.\n", test->getName());
        fprintf(stdout, "-------------------------------------------------------------------------------\n");
        fprintf(stdout, "%s", logger.getString());
        fprintf(stdout, "\n");
        fprintf(stdout, "Result  : %s\n", output.getData());
        fprintf(stdout, "Expected: %s\n", expected.getData());
        fprintf(stdout, "-------------------------------------------------------------------------------\n");
      }

      MemoryManager::getGlobal()->free(func);
    }
    else
    {
      fprintf(stdout, "[Failure] %s.\n", test->getName());
      fprintf(stdout, "-------------------------------------------------------------------------------\n");
      fprintf(stdout, "%s\n", logger.getString());
      fprintf(stdout, "-------------------------------------------------------------------------------\n");
    }

    fflush(stdout);
  }

  fputs("\n", stdout);
  fputs(testOutput.getData(), stdout);
  fflush(stdout);
}
예제 #14
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, 
      FuncBuilder8<Void, void*, void*, void*, void*, void*, void*, void*, void*>());

    GpVar p1(c.getGpArg(0));
    GpVar p2(c.getGpArg(1));
    GpVar p3(c.getGpArg(2));
    GpVar p4(c.getGpArg(3));
    GpVar p5(c.getGpArg(4));
    GpVar p6(c.getGpArg(5));
    GpVar p7(c.getGpArg(6));
    GpVar p8(c.getGpArg(7));

    c.add(p1, 1);
    c.add(p2, 2);
    c.add(p3, 3);
    c.add(p4, 4);
    c.add(p5, 5);
    c.add(p6, 6);
    c.add(p7, 7);
    c.add(p8, 8);

    // Move some data into buffer provided by arguments so we can verify if it
    // really works without looking into assembler output.
    c.add(byte_ptr(p1), imm(1));
    c.add(byte_ptr(p2), imm(2));
    c.add(byte_ptr(p3), imm(3));
    c.add(byte_ptr(p4), imm(4));
    c.add(byte_ptr(p5), imm(5));
    c.add(byte_ptr(p6), imm(6));
    c.add(byte_ptr(p7), imm(7));
    c.add(byte_ptr(p8), imm(8));

    c.endFunc();
  }
예제 #15
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder2<Void, int*, int*>());

    // Function arguments.
    GpVar a1(c.getGpArg(0));
    GpVar a2(c.getGpArg(1));

    // Create some variables.
    GpVar x1(c.newGpVar(kX86VarTypeGpd));
    GpVar x2(c.newGpVar(kX86VarTypeGpd));
    GpVar x3(c.newGpVar(kX86VarTypeGpd));
    GpVar x4(c.newGpVar(kX86VarTypeGpd));
    GpVar x5(c.newGpVar(kX86VarTypeGpd));
    GpVar x6(c.newGpVar(kX86VarTypeGpd));
    GpVar x7(c.newGpVar(kX86VarTypeGpd));
    GpVar x8(c.newGpVar(kX86VarTypeGpd));

    GpVar t(c.newGpVar(kX86VarTypeGpd));

    // Setup variables (use mov with reg/imm to se if register allocator works).
    c.mov(x1, 1);
    c.mov(x2, 2);
    c.mov(x3, 3);
    c.mov(x4, 4);
    c.mov(x5, 5);
    c.mov(x6, 6);
    c.mov(x7, 7);
    c.mov(x8, 8);

    // Make sum (addition).
    c.xor_(t, t);
    c.add(t, x1);
    c.add(t, x2);
    c.add(t, x3);
    c.add(t, x4);
    c.add(t, x5);
    c.add(t, x6);
    c.add(t, x7);
    c.add(t, x8);

    // Store result to a given pointer in first argument.
    c.mov(dword_ptr(a1), t);

    // Make sum (subtraction).
    c.xor_(t, t);
    c.sub(t, x1);
    c.sub(t, x2);
    c.sub(t, x3);
    c.sub(t, x4);
    c.sub(t, x5);
    c.sub(t, x6);
    c.sub(t, x7);
    c.sub(t, x8);

    // Store result to a given pointer in second argument.
    c.mov(dword_ptr(a2), t);

    // End of function.
    c.endFunc();
  }
예제 #16
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder0<int>());

    GpVar v0(c.newGpVar(kX86VarTypeGpd));
    GpVar v1(c.newGpVar(kX86VarTypeGpd));
    GpVar v2(c.newGpVar(kX86VarTypeGpd));
    GpVar v3(c.newGpVar(kX86VarTypeGpd));
    GpVar v4(c.newGpVar(kX86VarTypeGpd));

    c.xor_(v0, v0);

    c.mov(v1, 1);
    c.mov(v2, 2);
    c.mov(v3, 3);
    c.mov(v4, 4);

    c.add(v0, v1);
    c.add(v0, v2);
    c.add(v0, v3);
    c.add(v0, v4);

    c.ret(v0);
    c.endFunc();
  }
예제 #17
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder3<int, int, int, int>());

    GpVar x(c.getGpArg(0));
    GpVar y(c.getGpArg(1));
    GpVar op(c.getGpArg(2));

    GpVar result;
    X86CompilerFuncCall* fCall;

    Label opAdd(c.newLabel());
    Label opMul(c.newLabel());

    c.cmp(op, 0);
    c.jz(opAdd);
    c.cmp(op, 1);
    c.jz(opMul);

    result = c.newGpVar();
    c.mov(result, imm(0));
    c.ret(result);

    c.bind(opAdd);
    result = c.newGpVar();

    fCall = c.call((void*)calledFuncAdd);
    fCall->setPrototype(kX86FuncConvDefault, FuncBuilder2<int, int, int>());
    fCall->setArgument(0, x);
    fCall->setArgument(1, y);
    fCall->setReturn(result);
    c.ret(result);

    c.bind(opMul);
    result = c.newGpVar();

    fCall = c.call((void*)calledFuncMul);
    fCall->setPrototype(kX86FuncConvDefault, FuncBuilder2<int, int, int>());
    fCall->setArgument(0, x);
    fCall->setArgument(1, y);
    fCall->setReturn(result);
    c.ret(result);

    c.endFunc();
  }
예제 #18
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder3<Void, uint32_t*, const uint32_t*, size_t>());
    c.getFunc()->setHint(kFuncHintNaked, true);    // Omit unnecessary prolog/epilog.

    Label L_Loop = c.newLabel();                   // Create base labels we use
    Label L_Exit = c.newLabel();                   // in our function.

    GpVar dst(c.getGpArg(0));                      // Get reference to function
    GpVar src(c.getGpArg(1));                      // arguments.
    GpVar cnt(c.getGpArg(2));

    c.alloc(dst);                                  // Allocate all registers now,
    c.alloc(src);                                  // because we want to keep them
    c.alloc(cnt);                                  // in physical registers only.

    c.test(cnt, cnt);                              // Exit if length is zero.
    c.jz(L_Exit);

    c.bind(L_Loop);                                // Bind the loop label here.

    GpVar tmp(c.newGpVar(kX86VarTypeGpd));         // Copy a single dword (4 bytes).
    c.mov(tmp, dword_ptr(src));
    c.mov(dword_ptr(dst), tmp);

    c.add(src, 4);                                 // Increment dst/src pointers.
    c.add(dst, 4);

    c.dec(cnt);                                    // Loop until cnt isn't zero.
    c.jnz(L_Loop);

    c.bind(L_Exit);                                // Bind the exit label here.
    c.endFunc();                                   // End of function.
  }
예제 #19
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder0<int>());
    c.getFunc()->setHint(kFuncHintNaked, false);

    GpVar v0(c.newGpVar(kX86VarTypeGpd));
    GpVar v1(c.newGpVar(kX86VarTypeGpd));
    GpVar cnt(c.newGpVar(kX86VarTypeGpd));

    c.xor_(v0, v0);
    c.xor_(v1, v1);
    c.spill(v0);
    c.spill(v1);

    Label L(c.newLabel());
    c.mov(cnt, imm(32));
    c.bind(L);

    c.inc(v1);
    c.add(v0, v1);

    c.dec(cnt);
    c.jnz(L);

    c.ret(v0);
    c.endFunc();
  }
예제 #20
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvCompatFastCall, FuncBuilder1<int, int*>());
    c.getFunc()->setHint(kFuncHintNaked, true);

    GpVar buf(c.getGpArg(0));
    GpVar acc0(c.newGpVar(kX86VarTypeGpd));
    GpVar acc1(c.newGpVar(kX86VarTypeGpd));

    c.mov(acc0, 0);
    c.mov(acc1, 0);

    uint i;
    for (i = 0; i < 4; i++)
    {
      {
        GpVar ret = c.newGpVar(kX86VarTypeGpd);
        GpVar ptr = c.newGpVar(kX86VarTypeGpz);
        GpVar idx = c.newGpVar(kX86VarTypeGpd);

        c.mov(ptr, buf);
        c.mov(idx, imm(i));

        X86CompilerFuncCall* fCall = c.call((void*)calledFunc);
        fCall->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder2<int, int*, int>());
        fCall->setArgument(0, ptr);
        fCall->setArgument(1, idx);
        fCall->setReturn(ret);

        c.add(acc0, ret);
      }

      {
        GpVar ret = c.newGpVar(kX86VarTypeGpd);
        GpVar ptr = c.newGpVar(kX86VarTypeGpz);
        GpVar idx = c.newGpVar(kX86VarTypeGpd);

        c.mov(ptr, buf);
        c.mov(idx, imm(i));

        X86CompilerFuncCall* fCall = c.call((void*)calledFunc);
        fCall->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder2<int, int*, int>());
        fCall->setArgument(0, ptr);
        fCall->setArgument(1, idx);
        fCall->setReturn(ret);

        c.sub(acc1, ret);
      }
    }

    GpVar ret(c.newGpVar());
    c.mov(ret, acc0);
    c.add(ret, acc1);
    c.ret(ret);
    c.endFunc();
  }
예제 #21
0
  virtual void compile(X86Compiler& c)
  {
    switch (_argsCount)
    {
      case 0: c.newFunc(kX86FuncConvDefault, FuncBuilder0<int>()); break;
      case 1: c.newFunc(kX86FuncConvDefault, FuncBuilder1<int, int>()); break;
      case 2: c.newFunc(kX86FuncConvDefault, FuncBuilder2<int, int, int>()); break;
      case 3: c.newFunc(kX86FuncConvDefault, FuncBuilder3<int, int, int, int>()); break;
    }

    if (_naked  ) c.getFunc()->setHint(kFuncHintNaked, true);
    if (_pushPop) c.getFunc()->setHint(kX86FuncHintPushPop, true);

    GpVar gvar(c.newGpVar());
    XmmVar xvar(c.newXmmVar(kX86VarTypeXmm));

    // Alloc, use and spill preserved registers.
    if (_varsCount)
    {
      uint var = 0;
      uint index = 0;
      uint mask = 1;
      uint preserved = c.getFunc()->getDecl()->getGpPreservedMask();

      do {
        if ((preserved & mask) != 0 && (index != kX86RegIndexEsp && index != kX86RegIndexEbp))
        {
          GpVar somevar(c.newGpVar(kX86VarTypeGpd));
          c.alloc(somevar, index);
          c.mov(somevar, imm(0));
          c.spill(somevar);
          var++;
        }

        index++;
        mask <<= 1;
      } while (var < _varsCount && index < kX86RegNumGp);
    }

    c.alloc(gvar, zax);
    c.lea(gvar, xvar.m());
    c.and_(gvar, imm(15));
    c.ret(gvar);
    c.endFunc();
  }
예제 #22
0
  virtual void compile(X86Compiler& c)
  {
    c.newFunc(kX86FuncConvDefault, FuncBuilder0<Void>());

    Label L_A = c.newLabel();
    Label L_B = c.newLabel();
    Label L_C = c.newLabel();

    c.jmp(L_B);

    c.bind(L_A);
    c.jmp(L_C);

    c.bind(L_B);
    c.jmp(L_A);

    c.bind(L_C);

    c.ret();
    c.endFunc();
  }
예제 #23
0
static void benchX86(uint32_t arch, uint32_t callConv) {
  using namespace asmjit;

  Performance perf;
  TestRuntime runtime(arch, callConv);

  X86Assembler a(&runtime, arch);
  X86Compiler c;

  uint32_t r, i;

  const char* archName = arch == kArchX86 ? "X86" : "X64";

  // --------------------------------------------------------------------------
  // [Bench - Opcode]
  // --------------------------------------------------------------------------

  size_t asmOutputSize = 0;
  size_t cmpOutputSize = 0;

  perf.reset();
  for (r = 0; r < kNumRepeats; r++) {
    asmOutputSize = 0;
    perf.start();
    for (i = 0; i < kNumIterations; i++) {
      asmgen::opcode(a);

      void *p = a.make();
      runtime.release(p);

      asmOutputSize += a.getCodeSize();
      a.reset();
    }
    perf.end();
  }

  printf("%-12s (%s) | Time: %-6u [ms] | Speed: %7.3f [MB/s]\n",
    "X86Assembler", archName, perf.best, mbps(perf.best, asmOutputSize));

  // --------------------------------------------------------------------------
  // [Bench - Blend]
  // --------------------------------------------------------------------------

  perf.reset();
  for (r = 0; r < kNumRepeats; r++) {
    cmpOutputSize = 0;
    perf.start();
    for (i = 0; i < kNumIterations; i++) {
      c.attach(&a);
      asmgen::blend(c);
      c.finalize();

      void* p = a.make();
      runtime.release(p);

      cmpOutputSize += a.getCodeSize();
      a.reset();
    }
    perf.end();
  }

  printf("%-12s (%s) | Time: %-6u [ms] | Speed: %7.3f [MB/s]\n",
    "X86Compiler", archName, perf.best, mbps(perf.best, cmpOutputSize));
}
예제 #24
0
int main(int argc, char* argv[])
{
  using namespace AsmJit;

  // ==========================================================================
  // Log compiler output.
  FileLogger logger(stderr);
  logger.setLogBinary(true);

  // Create compiler.
  /*
  X86Compiler c;
  c.setLogger(&logger);

  c.newFunc(kX86FuncConvDefault, FuncBuilder0<Void>());
  c.getFunc()->setHint(kFuncHintNaked, true);

  X86CompilerFuncCall* ctx = c.call((void*)dummyFunc);
  ctx->setPrototype(kX86FuncConvDefault, FuncBuilder0<Void>());

  c.endFunc();
  */

  X86Compiler c;
  c.setLogger(&logger);

  c.newFunc(kX86FuncConvDefault, FuncBuilder0<void>());
  c.getFunc()->setHint(kFuncHintNaked, true);
  
  Label l91 = c.newLabel();
  Label l92 = c.newLabel();
  Label l93 = c.newLabel();
  Label l94 = c.newLabel();
  Label l95 = c.newLabel();
  Label l96 = c.newLabel();
  Label l97 = c.newLabel();
  c.bind(l92);

  GpVar _var91(c.newGpVar());
  GpVar _var92(c.newGpVar());
  
  c.bind(l93);
  c.jmp(l91);
  c.bind(l95);
  c.mov(_var91, imm(0));
  c.bind(l96);
  c.jmp(l93);
  c.mov(_var92, imm(1));
  c.jmp(l91);
  c.bind(l94);
  c.jmp(l92);
  c.bind(l97);
  c.add(_var91, _var92);
  c.bind(l91);
  c.ret();
  c.endFunc();
  
  typedef void (*Func9)(void);
  Func9 func9 = asmjit_cast<Func9>(c.make());
  // ==========================================================================

  // ==========================================================================
  // Make the function.
  // MyFn fn = asmjit_cast<MyFn>(c.make());

  // Call it.
  // printf("Result %llu\n", (unsigned long long)fn());

  // Free the generated function if it's not needed anymore.
  //MemoryManager::getGlobal()->free((void*)fn);
  // ==========================================================================

  return 0;
}