i'm trying learn way around llvm infrastructure. i've installed llvm binaries windows on mingw installation.
i'm following tutorial found on llvm site so-called kaleidoscope language. have source file has exactly code listing at end of page.
also, if it's of importance, i'm building using following flags (obtained through llvm-config ahead of time, because windows shell doesn't have comfortable substitution syntax):
clang++ -g -o3 kaleido.cpp -o kaleido.exe -ic:/mingw/include -dndebug -d__no_ctype_inline -d_gnu_source -d__stdc_constant_macros -d__stdc_format_macros -d__stdc_limit_macros -lc:/mingw/lib -lllvmcore -lllvmsupport -lpthread -lllvmx86disassembler -lllvmx86asmparser -lllvmx86codegen -lllvmselectiondag -lllvmasmprinter -lllvmmcparser -lllvmx86desc -lllvmx86info -lllvmx86asmprinter -lllvmx86utils -lllvmjit -lllvmruntimedyld -lllvmexecutionengine -lllvmcodegen -lllvmscalaropts -lllvminstcombine -lllvmtransformutils -lllvmipa -lllvmanalysis -lllvmtarget -lllvmmc -lllvmobject -lllvmcore -lllvmsupport -lm -limagehlp -lpsapi
using proposed language implemented in linked code, i'm testing few top level expressions. first, 1 literals:
ready> 5 + 3; ready> read top-level expression: define double @0() { entry: ret double 8.000000e+00 } evaluated 8.000000 ...works expected. function definition constant result:
ready> def f(x) 12; ready> read function definition: define double @f(double %x) { entry: ret double 1.200000e+01 } ...again, working expected. calling input gives fixed result:
ready> f(5); ready> read top-level expression: define double @1() { entry: %calltmp = call double @f(double 5.000000e+00) ret double %calltmp } evaluated 12.000000 ...no surprise. then, function definition parameter:
ready> def g(x) x + 1; ready> read function definition: define double @g(double %x) { entry: %addtmp = fadd double 1.000000e+00, %x ret double %addtmp } ...looks it's okay, bytecode generated. now, calling it:
ready> g(5); ready> read top-level expression: define double @2() { entry: %calltmp = call double @g(double 5.000000e+00) ret double %calltmp } 0x00d400a4 (0x0000000a 0x00000000 0x0028ff28 0x00d40087) <unknown module> 0x00c7a5e0 (0x01078a28 0x010cf040 0x0028fef0 0x40280000) 0x004023f1 (0x00000001 0x01072fd0 0x01071b10 0xffffffff) 0x004010b9 (0x00000001 0x00000000 0x00000000 0x00000000) 0x00401284 (0x7efde000 0x0028ffd4 0x77e59f42 0x7efde000) 0x75693677 (0x7efde000 0x7b3361a2 0x00000000 0x00000000), basethreadinitthunk() + 0x12 bytes(s) 0x77e59f42 (0x0040126c 0x7efde000 0x00000000 0x00000000), rtlinitializeexceptionchain() + 0x63 bytes(s) 0x77e59f15 (0x0040126c 0x7efde000 0x00000000 0x78746341), rtlinitializeexceptionchain() + 0x36 bytes(s) ...crashes.
through rudimentary debugging, i've come believe involved pieces of code, meaning 1 top-level expression (the call g(x) argument of 5) , 1 called function, both jit-compiled successfully. believe case because function pointer before crash (and i'm assuming execution engine returns function pointer after has compiled function). more precise, crash happens @ point function pointer run, meaning line in source file (in handletoplevelexpression()):
fprintf(stderr, "evaluated %f\n", fp()); most line innocent, because runs other functions. culprit somewhere inside function pointed fp in last of above examples, since code runtime generated, don't have in cpp file.
any ideas on why might crashing on specific scenario?
update #1: running process through gdb shows @ crash point:
program received signal sigill, illegal instruction.
and trace doesn't tell me anything:
0x00ee0044 in ?? () update #2: in attempt shed more light on this, here's assembly around crash:
00d70068 55 push ebp 00d70069 89e5 mov ebp,esp 00d7006b 81e4 f8ffffff , esp,fffffff8 00d70071 83ec 08 sub esp,8 00d70074 c5fb lds edi,ebx ; here! ; illegal use of register 00d70076 1045 08 adc byte ptr ss:[ebp+8],al 00d70079 c5fb lds edi,ebx ; illegal use of register 00d7007b 58 pop eax 00d7007c 05 6000d700 add eax,0d70060 00d70081 c5fb lds edi,ebx ; illegal use of register 00d70083 110424 adc dword ptr ss:[esp],eax 00d70086 dd0424 fld qword ptr ss:[esp] 00d70089 89ec mov esp,ebp 00d7008b 5d pop ebp 00d7008c c3 retn the crash happening @ 00d70074, instruction being lds edi,ebx. few addresses higher address pointed fp (which makes me believe might jit-emitted code, please take conclusion grain of salt, i'm on head here).
as can see, disassembler has placed comment on , next similar lines, saying it's illegal use of register. honest, don't know why specific extended register pair illegal instruction, if illegal, why there @ , how can make compiler produce legal code?
apparently llvm generating vex-prefixed avx instructions you, processor doesn't support instruction set (and neither disassembler).
avx-aware decoding of jit bytes give following valid code:
0: 55 push ebp 1: 89 e5 mov ebp,esp 3: 81 e4 f8 ff ff ff , esp,0xfffffff8 9: 83 ec 08 sub esp,0x8 c: c5 fb 10 45 08 vmovsd xmm0,qword ptr [ebp+0x8] 11: c5 fb 58 05 60 00 d7 vaddsd xmm0,xmm0,qword ptr ds:0xd70060 18: 00 19: c5 fb 11 04 24 vmovsd qword ptr [esp],xmm0 1e: dd 04 24 fld qword ptr [esp] 21: 89 ec mov esp,ebp 23: 5d pop ebp 24: c3 ret if llvm misdetecting native architecture, or if want override it, can change enginebuilder used in sample code, example like:
theexecutionengine = enginebuilder(themodule).seterrorstr(&errstr).setmcpu("i386").create(); you can set architecture or provide attributes.
Comments
Post a Comment