Hello, [Using LLVM r155315, according to `svn log | head`] I am experimenting with programatically building and jitting functions in a module, and I seem to be coming across a crash in some generated code. Using the llvm-c interface I build up the module which dumps like this: ; ModuleID = 'MyModule' target datalayout = "i686-apple-darwin11" target triple = "i686-apple-darwin11" define i32 @functionName(i32 %m, i32 %x, i32 %b) { entry: %mx = mul i32 %m, %x %y = add i32 %mx, %b ret i32 %y } Which looks OK to me. Note I'm not 100% sure (actually, I suspect is wrong) about the 'target datalayout' but with or without that line makes no difference to my results. When I attempt to run the JIT (interpreter works fine) I get a EXC_BAD_ACCESS with the following backtrace: * thread #1: tid = 0x2007, 0x0000000102e00042, stop reason = EXC_BAD_ACCESS (code=1, address=0x60c93a2c) frame #0: 0x0000000102e00042 frame #1: 0x00000001015c01fb LLVMPlayGround`llvm::JIT::runFunction(llvm::Function*, std::vector<llvm::GenericValue, std::allocator<llvm::GenericValue> > const&) + 4747 at JIT.cpp:547 frame #2: 0x00000001015a0db2 LLVMPlayGround`LLVMRunFunction + 322 at ExecutionEngineBindings.cpp:195 frame #3: 0x0000000101096125 LLVMPlayGround`main + 741 at main.c:91 frame #4: 0x0000000101095e34 LLVMPlayGround`start + 52 Which looks to be in some non-c code. At least XCode cannot find any corresponding source: 0x102e00042: movl $10, (%rsp) <-- DIE 0x102e00049: movl $5, 4(%rsp) 0x102e00051: movl $1, 8(%rsp) 0x102e00059: movl %eax, 24(%rsp) 0x102e0005d: movl %ecx, 20(%rsp) It looks like marshalling the 3 arguments to my function. Looking at rsp it looks like the top 32bits have been truncated, compared to other pointers floating around the system: rbp = 0x00007fff60c94070 rsp = 0x0000000060c93a2c r8 = 0x00007fff60c93800 r9 = 0x00007fff60c93808 If I use the debugger to poke 0x00007fff into the top half of rsp, stepping through works, and after one jump I get to my function; I see the mul and add instruction. Continuing to step, I need one more fixup of rsp (perhaps corresponding to two jitted functions: mine, and the auto-built nullary stub?) before returning to my main function. Is there anything obvious I've missed? Sorry for the long mail but I figure if I put all my data, then where I went wrong would be more obvious to someone who knows what they're doing :) Thanks, and please let me know if there's anything extra I can add. -DavidM PS: below is my complete source. #include <stdio.h> #define __STDC_LIMIT_MACROS #define __STDC_CONSTANT_MACROS #include "llvm-c/Core.h" #include "llvm-c/ExecutionEngine.h" int main(int argc, const char * argv[]) { LLVMContextRef llvm; llvm = LLVMContextCreate(); LLVMModuleRef module; module = LLVMModuleCreateWithNameInContext("MyModule", llvm); //LLVMSetDataLayout(module, "i686-apple-darwin11"); <-- is needed? What is correct? LLVMSetTarget(module, "i686-apple-darwin11"); LLVMTypeRef int32 = LLVMInt32TypeInContext(llvm); LLVMTypeRef funcType; LLVMTypeRef threeInts[] = {int32, int32, int32}; funcType = LLVMFunctionType(int32, threeInts, 3, 0); LLVMValueRef func; func = LLVMAddFunction(module, "functionName", funcType); LLVMValueRef mParam = LLVMGetParam(func, 0); LLVMSetValueName(mParam, "m"); LLVMValueRef xParam = LLVMGetParam(func, 1); LLVMSetValueName(xParam, "x"); LLVMValueRef bParam = LLVMGetParam(func, 2); LLVMSetValueName(bParam, "b"); LLVMBasicBlockRef entryBB; entryBB = LLVMAppendBasicBlockInContext(llvm, func, "entry"); LLVMBuilderRef builder; builder = LLVMCreateBuilderInContext(llvm); LLVMPositionBuilderAtEnd(builder, entryBB); LLVMValueRef mx; mx = LLVMBuildMul(builder, mParam, xParam, "mx"); LLVMValueRef y; y = LLVMBuildAdd(builder, mx, bParam, "y"); LLVMValueRef retInst; retInst = LLVMBuildRet(builder, y); (void) retInst; LLVMDisposeBuilder(builder); LLVMLinkInJIT(); LLVMLinkInInterpreter(); LLVMInitializeNativeTarget(); LLVMDumpModule(module); /* Now run it! */ LLVMExecutionEngineRef jit = NULL; char *err; // LLVMBool result = LLVMCreateExecutionEngineForModule(&jit, module, &err); LLVMBool result = LLVMCreateJITCompilerForModule(&jit, module, 0, &err); if (result) { printf("Fail: %s\n", err); return -1; } printf("JIT is %p\n", jit); LLVMGenericValueRef argM = LLVMCreateGenericValueOfInt(int32, 10, 0); LLVMGenericValueRef argX = LLVMCreateGenericValueOfInt(int32, 5, 0); LLVMGenericValueRef argB = LLVMCreateGenericValueOfInt(int32, 1, 0); LLVMGenericValueRef args[] = {argM, argX, argB}; LLVMGenericValueRef result2 = LLVMRunFunction(jit, func, 3, args); unsigned long long answer = LLVMGenericValueToInt(result2, 0); printf("And the answer is %d\n", (int)answer); LLVMDisposeModule(module); LLVMContextDispose(llvm); return 0; } -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120425/bb08fbdf/attachment.html>
Hi David, I'm not certain, but to me the "LLVMSetTarget(module, "i686-apple-darwin11");" line looks suspicious. I'm not familiar with all the ins and outs of how target triples get handled, but it looks to me like that's requesting 32-bit code. I think that if you omit that line completely then the target will be inferred from the execution environment. My best guess as to what you would want if you do want to specify something explicit is "x86_64-apple-darwin11". Someone who knows more about how the target works may correct me. -Andy From: llvmdev-bounces at cs.uiuc.edu [mailto:llvmdev-bounces at cs.uiuc.edu] On Behalf Of David Mirabito Sent: Tuesday, April 24, 2012 11:49 PM To: LLVM Developers Mailing List Subject: [LLVMdev] Crash in JIT Hello, [Using LLVM r155315, according to `svn log | head`] I am experimenting with programatically building and jitting functions in a module, and I seem to be coming across a crash in some generated code. Using the llvm-c interface I build up the module which dumps like this: ; ModuleID = 'MyModule' target datalayout = "i686-apple-darwin11" target triple = "i686-apple-darwin11" define i32 @functionName(i32 %m, i32 %x, i32 %b) { entry: %mx = mul i32 %m, %x %y = add i32 %mx, %b ret i32 %y } Which looks OK to me. Note I'm not 100% sure (actually, I suspect is wrong) about the 'target datalayout' but with or without that line makes no difference to my results. When I attempt to run the JIT (interpreter works fine) I get a EXC_BAD_ACCESS with the following backtrace: * thread #1: tid = 0x2007, 0x0000000102e00042, stop reason = EXC_BAD_ACCESS (code=1, address=0x60c93a2c) frame #0: 0x0000000102e00042 frame #1: 0x00000001015c01fb LLVMPlayGround`llvm::JIT::runFunction(llvm::Function*, std::vector<llvm::GenericValue, std::allocator<llvm::GenericValue> > const&) + 4747 at JIT.cpp:547 frame #2: 0x00000001015a0db2 LLVMPlayGround`LLVMRunFunction + 322 at ExecutionEngineBindings.cpp:195 frame #3: 0x0000000101096125 LLVMPlayGround`main + 741 at main.c:91 frame #4: 0x0000000101095e34 LLVMPlayGround`start + 52 Which looks to be in some non-c code. At least XCode cannot find any corresponding source: 0x102e00042: movl $10, (%rsp) <-- DIE 0x102e00049: movl $5, 4(%rsp) 0x102e00051: movl $1, 8(%rsp) 0x102e00059: movl %eax, 24(%rsp) 0x102e0005d: movl %ecx, 20(%rsp) It looks like marshalling the 3 arguments to my function. Looking at rsp it looks like the top 32bits have been truncated, compared to other pointers floating around the system: rbp = 0x00007fff60c94070 rsp = 0x0000000060c93a2c r8 = 0x00007fff60c93800 r9 = 0x00007fff60c93808 If I use the debugger to poke 0x00007fff into the top half of rsp, stepping through works, and after one jump I get to my function; I see the mul and add instruction. Continuing to step, I need one more fixup of rsp (perhaps corresponding to two jitted functions: mine, and the auto-built nullary stub?) before returning to my main function. Is there anything obvious I've missed? Sorry for the long mail but I figure if I put all my data, then where I went wrong would be more obvious to someone who knows what they're doing :) Thanks, and please let me know if there's anything extra I can add. -DavidM PS: below is my complete source. #include <stdio.h> #define __STDC_LIMIT_MACROS #define __STDC_CONSTANT_MACROS #include "llvm-c/Core.h" #include "llvm-c/ExecutionEngine.h" int main(int argc, const char * argv[]) { LLVMContextRef llvm; llvm = LLVMContextCreate(); LLVMModuleRef module; module = LLVMModuleCreateWithNameInContext("MyModule", llvm); //LLVMSetDataLayout(module, "i686-apple-darwin11"); <-- is needed? What is correct? LLVMSetTarget(module, "i686-apple-darwin11"); LLVMTypeRef int32 = LLVMInt32TypeInContext(llvm); LLVMTypeRef funcType; LLVMTypeRef threeInts[] = {int32, int32, int32}; funcType = LLVMFunctionType(int32, threeInts, 3, 0); LLVMValueRef func; func = LLVMAddFunction(module, "functionName", funcType); LLVMValueRef mParam = LLVMGetParam(func, 0); LLVMSetValueName(mParam, "m"); LLVMValueRef xParam = LLVMGetParam(func, 1); LLVMSetValueName(xParam, "x"); LLVMValueRef bParam = LLVMGetParam(func, 2); LLVMSetValueName(bParam, "b"); LLVMBasicBlockRef entryBB; entryBB = LLVMAppendBasicBlockInContext(llvm, func, "entry"); LLVMBuilderRef builder; builder = LLVMCreateBuilderInContext(llvm); LLVMPositionBuilderAtEnd(builder, entryBB); LLVMValueRef mx; mx = LLVMBuildMul(builder, mParam, xParam, "mx"); LLVMValueRef y; y = LLVMBuildAdd(builder, mx, bParam, "y"); LLVMValueRef retInst; retInst = LLVMBuildRet(builder, y); (void) retInst; LLVMDisposeBuilder(builder); LLVMLinkInJIT(); LLVMLinkInInterpreter(); LLVMInitializeNativeTarget(); LLVMDumpModule(module); /* Now run it! */ LLVMExecutionEngineRef jit = NULL; char *err; // LLVMBool result = LLVMCreateExecutionEngineForModule(&jit, module, &err); LLVMBool result = LLVMCreateJITCompilerForModule(&jit, module, 0, &err); if (result) { printf("Fail: %s\n", err); return -1; } printf("JIT is %p\n", jit); LLVMGenericValueRef argM = LLVMCreateGenericValueOfInt(int32, 10, 0); LLVMGenericValueRef argX = LLVMCreateGenericValueOfInt(int32, 5, 0); LLVMGenericValueRef argB = LLVMCreateGenericValueOfInt(int32, 1, 0); LLVMGenericValueRef args[] = {argM, argX, argB}; LLVMGenericValueRef result2 = LLVMRunFunction(jit, func, 3, args); unsigned long long answer = LLVMGenericValueToInt(result2, 0); printf("And the answer is %d\n", (int)answer); LLVMDisposeModule(module); LLVMContextDispose(llvm); return 0; } -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120425/d2bd6a0b/attachment.html>
Hi Andy, You are of course correct. My mail bounced because I forgot I wasn't actually subscribed (fixed that too!) and in the meantime I nutted it out on IRC. So it turns out with that triple, it was generating a 32-bit stack manipulation ('subl #12' - which had scrolled away in XCode when I pasted into my original email), which cleared the top bits and caused trouble. Changing the triple to exactly as you mentioned means things start to work perfectly. My x86/x64 is pretty terrible so it took me longer to figure exactly what was happening than maybe it should have :) Although I am somewhat (but not overly) surprised the execution engine accepted the module with such a target, and didn't complain that it didn't match 'InitializeNativeTarget()'. But for now I'm just glad it works. I've since managed to get the JIT'd code to import and call helper functions my app provides - it's really *cool* stuff and am excited to further the project! Cheers for the tips, DavidM On 25/04/2012, at 6:36 PM, Kaylor, Andrew wrote:> Hi David, > > I’m not certain, but to me the “LLVMSetTarget(module, "i686-apple-darwin11");” line looks suspicious. I’m not familiar with all the ins and outs of how target triples get handled, but it looks to me like that’s requesting 32-bit code. > > I think that if you omit that line completely then the target will be inferred from the execution environment. My best guess as to what you would want if you do want to specify something explicit is “x86_64-apple-darwin11”. > > Someone who knows more about how the target works may correct me. > > -Andy > > From: llvmdev-bounces at cs.uiuc.edu [mailto:llvmdev-bounces at cs.uiuc.edu] On Behalf Of David Mirabito > Sent: Tuesday, April 24, 2012 11:49 PM > To: LLVM Developers Mailing List > Subject: [LLVMdev] Crash in JIT > > Hello, > > [Using LLVM r155315, according to `svn log | head`] > > I am experimenting with programatically building and jitting functions in a module, and I seem to be coming across a crash in some generated code. Using the llvm-c interface I build up the module which dumps like this: > ; ModuleID = 'MyModule' > target datalayout = "i686-apple-darwin11" > target triple = "i686-apple-darwin11" > > define i32 @functionName(i32 %m, i32 %x, i32 %b) { > entry: > %mx = mul i32 %m, %x > %y = add i32 %mx, %b > ret i32 %y > } > > Which looks OK to me. Note I'm not 100% sure (actually, I suspect is wrong) about the 'target datalayout' but with or without that line makes no difference to my results. > > When I attempt to run the JIT (interpreter works fine) I get a EXC_BAD_ACCESS with the following backtrace: > * thread #1: tid = 0x2007, 0x0000000102e00042, stop reason = EXC_BAD_ACCESS (code=1, address=0x60c93a2c) > frame #0: 0x0000000102e00042 > frame #1: 0x00000001015c01fb LLVMPlayGround`llvm::JIT::runFunction(llvm::Function*, std::vector<llvm::GenericValue, std::allocator<llvm::GenericValue> > const&) + 4747 at JIT.cpp:547 > frame #2: 0x00000001015a0db2 LLVMPlayGround`LLVMRunFunction + 322 at ExecutionEngineBindings.cpp:195 > frame #3: 0x0000000101096125 LLVMPlayGround`main + 741 at main.c:91 > frame #4: 0x0000000101095e34 LLVMPlayGround`start + 52 > > Which looks to be in some non-c code. At least XCode cannot find any corresponding source: > 0x102e00042: movl $10, (%rsp) <-- DIE > 0x102e00049: movl $5, 4(%rsp) > 0x102e00051: movl $1, 8(%rsp) > 0x102e00059: movl %eax, 24(%rsp) > 0x102e0005d: movl %ecx, 20(%rsp) > It looks like marshalling the 3 arguments to my function. > > Looking at rsp it looks like the top 32bits have been truncated, compared to other pointers floating around the system: > rbp = 0x00007fff60c94070 > rsp = 0x0000000060c93a2c > r8 = 0x00007fff60c93800 > r9 = 0x00007fff60c93808 > > If I use the debugger to poke 0x00007fff into the top half of rsp, stepping through works, and after one jump I get to my function; I see the mul and add instruction. Continuing to step, I need one more fixup of rsp (perhaps corresponding to two jitted functions: mine, and the auto-built nullary stub?) before returning to my main function. > > Is there anything obvious I've missed? Sorry for the long mail but I figure if I put all my data, then where I went wrong would be more obvious to someone who knows what they're doing :) > > Thanks, and please let me know if there's anything extra I can add. > -DavidM > > PS: below is my complete source. > > > #include <stdio.h> > #define __STDC_LIMIT_MACROS > #define __STDC_CONSTANT_MACROS > > #include "llvm-c/Core.h" > #include "llvm-c/ExecutionEngine.h" > > int main(int argc, const char * argv[]) > { > > LLVMContextRef llvm; > llvm = LLVMContextCreate(); > > LLVMModuleRef module; > module = LLVMModuleCreateWithNameInContext("MyModule", llvm); > //LLVMSetDataLayout(module, "i686-apple-darwin11"); <-- is needed? What is correct? > LLVMSetTarget(module, "i686-apple-darwin11"); > > > LLVMTypeRef int32 = LLVMInt32TypeInContext(llvm); > > LLVMTypeRef funcType; > LLVMTypeRef threeInts[] = {int32, int32, int32}; > funcType = LLVMFunctionType(int32, threeInts, 3, 0); > > LLVMValueRef func; > func = LLVMAddFunction(module, "functionName", funcType); > > LLVMValueRef mParam = LLVMGetParam(func, 0); > LLVMSetValueName(mParam, "m"); > > LLVMValueRef xParam = LLVMGetParam(func, 1); > LLVMSetValueName(xParam, "x"); > > LLVMValueRef bParam = LLVMGetParam(func, 2); > LLVMSetValueName(bParam, "b"); > > LLVMBasicBlockRef entryBB; > entryBB = LLVMAppendBasicBlockInContext(llvm, func, "entry"); > > LLVMBuilderRef builder; > builder = LLVMCreateBuilderInContext(llvm); > > LLVMPositionBuilderAtEnd(builder, entryBB); > > LLVMValueRef mx; > mx = LLVMBuildMul(builder, mParam, xParam, "mx"); > > LLVMValueRef y; > y = LLVMBuildAdd(builder, mx, bParam, "y"); > > LLVMValueRef retInst; > retInst = LLVMBuildRet(builder, y); > (void) retInst; > > > LLVMDisposeBuilder(builder); > > > LLVMLinkInJIT(); > LLVMLinkInInterpreter(); > LLVMInitializeNativeTarget(); > > LLVMDumpModule(module); > > /* Now run it! */ > > LLVMExecutionEngineRef jit = NULL; > char *err; > // LLVMBool result = LLVMCreateExecutionEngineForModule(&jit, module, &err); > LLVMBool result = LLVMCreateJITCompilerForModule(&jit, module, 0, &err); > if (result) { > printf("Fail: %s\n", err); > return -1; > } > printf("JIT is %p\n", jit); > > LLVMGenericValueRef argM = LLVMCreateGenericValueOfInt(int32, 10, 0); > LLVMGenericValueRef argX = LLVMCreateGenericValueOfInt(int32, 5, 0); > LLVMGenericValueRef argB = LLVMCreateGenericValueOfInt(int32, 1, 0); > > LLVMGenericValueRef args[] = {argM, argX, argB}; > LLVMGenericValueRef result2 = LLVMRunFunction(jit, func, 3, args); > unsigned long long answer = LLVMGenericValueToInt(result2, 0); > printf("And the answer is %d\n", (int)answer); > > LLVMDisposeModule(module); > LLVMContextDispose(llvm); > return 0; > } >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120425/d0ef1754/attachment.html>