Built-in REPL doesn't work on Linux (x86-64)?


(David Zarzycki) #1

I'm confused about the built-in REPL and how it is tested. The validation test suite passes on my x86-64 Linux box, but "let x = 42" crashes in practice. This feels surprising. Is there a large gap in the REPL testing? Also, a quick investigation shows that the code crashes in the middle of an instruction in the middle of the JIT'ed "main()", but I don't see any obvious way the code would have jumped there.

$ ./bin/swift
***  You are running Swift's integrated REPL,  ***
***  intended for compiler and stdlib          ***
***  development and testing purposes only.    ***
***  The full REPL is built as part of LLDB.   ***
***  Type ':help' for assistance.              ***
(swift) let x = 42
Stack dump:
0.	Program arguments: /home/dave/s/u/d/bin/swift -frontend -repl -disable-objc-interop -color-diagnostics -module-name REPL 
1.	while processing REPL source:
let x = 42
#0 0x000000000b555629 llvm::sys::PrintStackTrace(llvm::raw_ostream&) /home/dave/s/u/d/../lib/Support/Unix/Signals.inc:490:11
#1 0x000000000b555849 PrintStackTraceSignalHandler(void*) /home/dave/s/u/d/../lib/Support/Unix/Signals.inc:554:1
#2 0x000000000b5527e4 llvm::sys::RunSignalHandlers() /home/dave/s/u/d/../lib/Support/Signals.cpp:67:5
#3 0x000000000b5563f4 SignalHandler(int) /home/dave/s/u/d/../lib/Support/Unix/Signals.inc:353:1
#4 0x000014829d2cb070 __restore_rt (/lib64/libpthread.so.0+0x13070)
#5 0x000014829d316120
#6 0x00000000045aa17f llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) /home/dave/s/u/d/../lib/ExecutionEngine/MCJIT/MCJIT.cpp:548:31
#7 0x00000000045b8a1f llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) /home/dave/s/u/d/../lib/ExecutionEngine/ExecutionEngine.cpp:471:34
#8 0x0000000003510f50 REPLEnvironment::executeSwiftSource(llvm::StringRef, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) /home/dave/s/u/d/../tools/swift/lib/Immediate/REPL.cpp:948:5
#9 0x0000000003506290 REPLEnvironment::handleREPLInput((anonymous namespace)::REPLInputKind, llvm::StringRef) /home/dave/s/u/d/../tools/swift/lib/Immediate/REPL.cpp:1193:9
#10 0x00000000035030c7 swift::runREPL(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, bool) /home/dave/s/u/d/../tools/swift/lib/Immediate/REPL.cpp:1220:3
#11 0x0000000003429c4f performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) /home/dave/s/u/d/../tools/swift/lib/FrontendTool/FrontendTool.cpp:982:5
#12 0x000000000342829d swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) /home/dave/s/u/d/../tools/swift/lib/FrontendTool/FrontendTool.cpp:1839:8
#13 0x000000000334892a run_driver(llvm::StringRef, llvm::ArrayRef<char const*>) /home/dave/s/u/d/../tools/swift/tools/driver/driver.cpp:122:7
#14 0x0000000003347a08 main /home/dave/s/u/d/../tools/swift/tools/driver/driver.cpp:246:5
#15 0x000014829b5e5413 __libc_start_main (/lib64/libc.so.6+0x24413)
#16 0x000000000333f02e _start (/home/dave/s/u/d/bin/swift+0x333f02e)
Illegal instruction

(Jordan Rose) #2

There's basically no testing of the integrated REPL because end users use the LLDB REPL. It's purely for convenience developing the compiler. What is supposed to work is using swift as a JITing script runner, though, and that's definitely undertested. You can see whether the problem is in the JIT or specific to the REPL with

echo 'let x = 42' | bin/swift -

(Because it has an input, -, that's a script-running command rather than a REPL command.)


(David Zarzycki) #3

Do the REPL tests in test/Interpreter not [smoke] test the integrated REPL? I thought they did. In any case, the script runner works. Is there a secret or easy way to turn off the printing of values after evaluating a line? That seems useful for triage.


(Jordan Rose) #4

:-/ There's a few integrated REPL tests in test/Interpreter/, but mostly that's just "test/execution/" these days. (A bunch of them were interpreter / JIT / script runner tests a long time ago, but they got converted to compile-and-run tests when we started caring about iOS and other forms of cross-compilation.)

Feel free to add random testing options to lib/Immediate/REPL.cpp.