C で curry 化 @x86

http://nicosia.is.s.u-tokyo.ac.jp/pub/essay/hagiya/h/curry

を Sun から x86 に。

C言語は便利で楽しいなあ、と思わざる得ないのである。

に激しく同意なのです。

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

int (*curry(int (*F)(), int A))() {
  char *code = (char*)malloc(18);

  *(char*)code = 0x55;
  *(short int*)(code+1) = 0xe589;
  *(short int*)(code+3) = 0x75ff;
  *(char*)(code+5) = 0x08;
  *(char*)(code+6) = 0x6a;
  *(char*)(code+7) = (char)A;
  *(char*)(code+8) = 0xe8;
  *(int*)(code+9) = (int)F-((int)code+9+4);
  *(short int*)(code+13) = 0xc483;
  *(short int*)(code+15) = 0x08;
  *(short int*)(code+16) = 0xc9;
  *(short int*)(code+17) = 0xc3;

  mprotect((void*)(((int)code+4095) & ~4095 - 4096),
           4096, PROT_READ | PROT_EXEC);

  return((int (*)())code);
}

int add(int x, int y) {
  return(x + y);
}

int main() {
  int (*c)();

  c = curry(add, 100);
  printf("%d\n", (*c)(10));
}

C で curry 化 @lightning

さて上記をポータブルに。 GNU lightning の出番。

http://www.gnu.org/software/lightning/lightning.html

下記コードは i386-linuxppc-macosxsparc-solaris で動きました。

#include <stdio.h>

#include "lightning.h"

typedef int (*pifi)(int);
static jit_insn buf[1024];

int (*curry(int (*F)(), int A))() {
    pifi code = (pifi)(jit_set_ip(buf).iptr);
    int i;

    jit_prolog(1);
    i = jit_arg_ui();
    jit_getarg_ui(JIT_V0, i);
    jit_movi_i(JIT_V1, A);
    jit_prepare(2);
    jit_pusharg_ui(JIT_V1);
    jit_pusharg_ui(JIT_V0);
    jit_finish(F);
    jit_retval(JIT_RET);
    jit_ret();
    jit_flush_code(buf, jit_get_ip().ptr);

    return code;
}

int add(int x, int y) {
    return(x + y);
}

int main() {
    int (*c)();

    c = curry(add, 100);
    printf("%d\n", (*c)(10));
}

あら簡単。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h