Conversation
359df26 to
1a82928
Compare
1a82928 to
c0bdf7a
Compare
e90538e to
da2ed66
Compare
5196d26 to
35d273b
Compare
35d273b to
959df9d
Compare
| "pop %rbx\n\t" | ||
| "retq" | ||
| ); | ||
| #endif |
There was a problem hiding this comment.
@YoheiKakiuchi このコードってどうやって作るんですか?
#395 見ているんだけど,
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <setjmp.h>
#include <errno.h>
#include <dlfcn.h>
#include <eus.h> // include eus.h just for eusfloat_t ...
union god{
int body;
float spirit;
};
union god human;
union god monkey;
void _test1(int i ) {
monkey.body = i;
printf("_test1: %d %f\n", monkey.body, monkey.spirit);
}
void _test2(int i , float f) {
monkey.body = i;
printf("_test2: %d %f\n", i, f);
printf("_test2: %d %f\n", monkey.body, monkey.spirit);
}
int main(int argc, char **argv)
{
float malice = 2.5;
human.spirit = malice;
printf("%ld %ld\n", sizeof(float), sizeof(int));
printf("main : %d %f\n", human.body, human.spirit);
printf("_test1(human.body)\n");
_test1(human.body);
printf("_test2(human.body, human.spirit)\n");
_test2(human.body, human.spirit);
eusinteger_t (*ifunc)(); /* ???? */
void * handle = dlopen("libtestdefforeign.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(-1);
}
//ifunc = (pointer)dlsym((void *)((eusinteger_t)(handle, "test1")));
ifunc = (pointer)dlsym(handle, "test1");
double (*ffunc)();
ffunc=(double (*)())ifunc;
printf("ffunc(human.body, human.spirit)\n");
ffunc(human.body, human.spirit);
eusinteger_t cargv[100];
cargv[0] = human.body;
cargv[1] = human.body;
printf("ffunc(cargv[0], cargv[1])\n");
ffunc(cargv[0], cargv[1]);
numunion nargv[100];
nargv[0].ival = human.body;
nargv[1].fval = human.spirit;
printf("ffunc(nargv[0], nargv[1])\n");
ffunc(nargv[0], nargv[1]);
float (*ffunc2)(int, float);
ffunc2=(float (*)(int, float))ifunc;
printf("ffunc(human.body, human.spirit)\n");
ffunc(human.body, human.spirit);
return 0;
}
(gcc -DLinux -DGCC -I/root/jskeus/eus/lisp/c -falign-functions=4 -o hoge hoge.c -ldl && ./hoge)
みたいにしているんだけど,これでも上手くいかないので,exec_function_iみたいなのを作らないといけないのかな,って.よく分かっていないんですが.
|
長くなっていますが、function callのアセンブリについての解説です。 問題のarmhfについては最後に書いてあります。 Foreign Function Call でやりたいこと実行時に、引数と返り値の定義が分かっている、既知アドレスに定義されている関数をコールしたい。 コンパイラがやってくれている、引数の定義から値を適切なレジスタにセットし、コールして、 x86_64例えばこの資料 ( 'x86_64 ABI' などとgoogleさんに聞く) https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf 資料の 3.2.3 Parameter Passing に関数を呼ぶ時の引数の渡し方について書いてある。 ここで、eval.c では INTEGER(char,short,int,long,pointer) と SSE(float,double)についてだけ実装している 簡単に書くと、引数については、
返り値については、
資料の Figure 3.5: Parameter Passing Example が分かりやすい eval.cのコード実際のcall_foreignでは、 (コードのこの部分 https://github.com/euslisp/EusLisp/blob/EusLisp-9.27/lisp/c/eval.c#L871-L949 ) その後、 exec_function_xxxの内部では、 呼出し後、floatは型変換する (コードのこの部分 https://github.com/euslisp/EusLisp/blob/EusLisp-9.27/lisp/c/eval.c#L951-L959 ) 上記のように、返り値がlong/doubleの2つ用意してある意味は、返り値の種類によって入っているレジスタが違うのを解消するため。 対応していないのは
aarm64例えばこの資料 ( 'Procedure Call Standard for the ARM 64-bit Architecture' などとgoogleさんに聞く) なんかレジスタの名前が違う気がする。。。 レジスタ 浮動小数点レジスタ 簡単に書くと、引数については、
返り値については、
とほぼ、x86_64とやっていることについて同じ。 armhfarmで32bitだが浮動小数点演算器が搭載されていてそれを使うもの https://developer.arm.com/docs/ihi0042/latest
返り値については、
と書いてあるように見えます。 なので、intelの32bitのようには出来なくて、exec_function_i/fを書く必要があるかと思います。 floatとdoubleで場合分けが入っているようにも見えて、floatとdoubleの混合の場合はどうなるかなどアセンブラコードを見ないと分からないです。 aarch64と微妙に異なるので、新たにarmhfだけに対応するexec_function_i/fと、 exec_function_i/fについては、アセンブラのコードを書く必要があります。 32bitと64bitで違いそうなところ
アセンブラは test.c (exec_function_iと引数が同じ関数をアセンブラ化してみる)
test.s 引数を渡すところ、返り値をセットするところを参考にして、それ以外の部分はアセンブラを書く。 |
|
@YoheiKakiuchi ありがとうございます みたいにでてくるコードが違うんですが,上のコードはどうやって作ったでしょうか? |
|
すいません。コマンドのヒストリをたどると、arm64での結果だったようです。 こちらで確認したら、岡田先生のと同じでした。 |
|
@YoheiKakiuchi |
|
あと、スタックに積まれる場合も、doubleは8byte、floatは4byteで積まれるので、それも対応必要ありそうです。 x86_64はスタックは常に8byteで使うので大丈夫だと思います。 |
|
なるほどね. |
No description provided.