Reactor: Implement debug info generation

Currently only works on Linux + GDB.

See docs/ReactorDebugInfo.md for details.

Change-Id: I73d47d0492f6ccfc07eec4d4084332b4991fd515
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27949
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a07454a..9bd3a17 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,6 +81,7 @@
 option (UBSAN "Build with undefined behavior sanitizer" 0)
 option (WARNINGS_AS_ERRORS "Treat all warnings as errors" 1)
 option (DCHECK_ALWAYS_ON "Check validation macros even in release builds" 0)
+option (REACTOR_EMIT_DEBUG_INFO "Emit debug info for JIT functions" 0)
 
 if(ARCH STREQUAL "arm")
     set(DEFAULT_REACTOR_BACKEND "Subzero")
@@ -205,6 +206,9 @@
     set(LLVM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/llvm-7.0/llvm)
     set(LLVM_CONFIG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/llvm-7.0/configs)
 endif()
+set(LIBBACKTRACE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libbacktrace/src)
+set(LIBBACKTRACE_CONFIG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libbacktrace/config)
+set(LIBBACKTRACE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libbacktrace/src)
 set(SUBZERO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/subzero)
 set(SUBZERO_LLVM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/llvm-subzero)
 set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests)
@@ -293,6 +297,10 @@
         set_cpp_flag("-DDCHECK_ALWAYS_ON")
     endif()
 
+    if(REACTOR_EMIT_DEBUG_INFO)
+        set_cpp_flag("-DENABLE_RR_DEBUG_INFO")
+    endif()
+
     # Disable pedanitc warnings
     if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
         set_cpp_flag("-Wno-ignored-attributes")  # ignoring attributes on template argument 'X'
@@ -1762,18 +1770,28 @@
         ${LLVM_DIR}/lib/Target/ARM/ARMLegalizerInfo.cpp
         ${LLVM_DIR}/lib/Target/ARM/ARMOptimizeBarriersPass.cpp
     )
- endif()
+endif()
+
+if(REACTOR_EMIT_DEBUG_INFO)
+    list(APPEND LLVM_LIST
+        ${LLVM_DIR}/lib/Demangle/ItaniumDemangle.cpp
+    )
+endif(REACTOR_EMIT_DEBUG_INFO)
 
 set(LLVM_INCLUDE_DIR "")
 
 if(WIN32)
     list(APPEND LLVM_INCLUDE_DIR ${LLVM_CONFIG_DIR}/windows/include)
+    list(APPEND LIBBACKTRACE_INCLUDE_DIR ${LIBBACKTRACE_CONFIG_DIR}/windows/include)
 elseif(LINUX)
     list(APPEND LLVM_INCLUDE_DIR ${LLVM_CONFIG_DIR}/linux/include)
+    list(APPEND LIBBACKTRACE_INCLUDE_DIR ${LIBBACKTRACE_CONFIG_DIR}/linux/include)
 elseif(APPLE)
     list(APPEND LLVM_INCLUDE_DIR ${LLVM_CONFIG_DIR}/darwin/include)
+    list(APPEND LIBBACKTRACE_INCLUDE_DIR ${LIBBACKTRACE_CONFIG_DIR}/darwin/include)
 elseif(ANDROID)
     list(APPEND LLVM_INCLUDE_DIR ${LLVM_CONFIG_DIR}/android/include)
+    list(APPEND LIBBACKTRACE_INCLUDE_DIR ${LIBBACKTRACE_CONFIG_DIR}/android/include)
 endif()
 
 list(APPEND LLVM_INCLUDE_DIR
@@ -1962,6 +1980,7 @@
     ${SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/include
     ${LLVM_INCLUDE_DIR}
+    ${LIBBACKTRACE_INCLUDE_DIR}
 )
 set(OPENGL_INCLUDE_DIR
     ${OPENGL_DIR}
@@ -2002,9 +2021,41 @@
     ${SOURCE_DIR}/Common/GrallocAndroid.hpp
 )
 
+if(REACTOR_EMIT_DEBUG_INFO)
+    set(LIBBACKTRACE_LIST
+        ${LIBBACKTRACE_DIR}/atomic.c
+        ${LIBBACKTRACE_DIR}/backtrace.c
+        ${LIBBACKTRACE_DIR}/backtrace.h
+        ${LIBBACKTRACE_DIR}/dwarf.c
+        ${LIBBACKTRACE_DIR}/fileline.c
+        ${LIBBACKTRACE_DIR}/filenames.h
+        ${LIBBACKTRACE_DIR}/internal.h
+        ${LIBBACKTRACE_DIR}/mmap.c
+        ${LIBBACKTRACE_DIR}/mmapio.c
+        ${LIBBACKTRACE_DIR}/posix.c
+        ${LIBBACKTRACE_DIR}/print.c
+        ${LIBBACKTRACE_DIR}/simple.c
+        ${LIBBACKTRACE_DIR}/sort.c
+        ${LIBBACKTRACE_DIR}/state.c
+        ${LIBBACKTRACE_INCLUDE_DIR}/backtrace-supported.h
+        ${LIBBACKTRACE_INCLUDE_DIR}/config.h
+    )
+
+    if(WIN32)
+        list(APPEND LIBBACKTRACE_LIST ${LIBBACKTRACE_DIR}/pecoff.c)
+    elseif(LINUX)
+        list(APPEND LIBBACKTRACE_LIST ${LIBBACKTRACE_DIR}/elf.c)
+    elseif(APPLE)
+        message(FATAL_ERROR "libbacktrace does not support mach-o yet")
+    endif()
+endif(REACTOR_EMIT_DEBUG_INFO)
+
 set(REACTOR_LLVM_LIST
     ${SOURCE_DIR}/Reactor/Reactor.cpp
     ${SOURCE_DIR}/Reactor/LLVMReactor.cpp
+    ${SOURCE_DIR}/Reactor/LLVMReactor.hpp
+    ${SOURCE_DIR}/Reactor/LLVMReactorDebugInfo.cpp
+    ${SOURCE_DIR}/Reactor/LLVMReactorDebugInfo.hpp
     ${SOURCE_DIR}/Reactor/Nucleus.hpp
     ${SOURCE_DIR}/Reactor/Routine.cpp
     ${SOURCE_DIR}/Reactor/Routine.hpp
@@ -2202,6 +2253,17 @@
 )
 target_link_libraries(ReactorLLVM llvm ${OS_LIBS})
 
+if(REACTOR_EMIT_DEBUG_INFO)
+    add_library(Libbacktrace STATIC ${LIBBACKTRACE_LIST})
+    set_target_properties(Libbacktrace PROPERTIES
+        INCLUDE_DIRECTORIES "${LIBBACKTRACE_INCLUDE_DIR}"
+        POSITION_INDEPENDENT_CODE 1
+        FOLDER "Core"
+    )
+    target_link_libraries(Libbacktrace ${OS_LIBS})
+    target_link_libraries(ReactorLLVM Libbacktrace)
+endif(REACTOR_EMIT_DEBUG_INFO)
+
 if(${REACTOR_BACKEND} STREQUAL "LLVM")
     set(Reactor ReactorLLVM)
 elseif(${REACTOR_BACKEND} STREQUAL "Subzero")
diff --git a/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj b/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj
index 839919d..5371a2e 100644
--- a/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj
+++ b/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj
@@ -122,7 +122,10 @@
   </ItemDefinitionGroup>

   <ItemGroup>

     <ClCompile Include="$(SolutionDir)src\Reactor\Reactor.cpp" />

-    <ClCompile Include="$(SolutionDir)src\Reactor\LLVMReactor.cpp" />

+    <ClCompile Include="$(SolutionDir)src\Reactor\LLVMReactor.cpp"  />

+    <ClInclude Include="$(SolutionDir)src\Reactor\LLVMReactor.hpp" />

+    <ClCompile Include="$(SolutionDir)src\Reactor\LLVMReactorDebugInfo.cpp"  />

+    <ClInclude Include="$(SolutionDir)src\Reactor\LLVMReactorDebugInfo.hpp" />

     <ClInclude Include="$(SolutionDir)src\Reactor\Nucleus.hpp" />

     <ClCompile Include="$(SolutionDir)src\Reactor\Routine.cpp" />

     <ClInclude Include="$(SolutionDir)src\Reactor\Routine.hpp" />

diff --git a/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj.filters b/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj.filters
index 8848ab0..cdd429e 100644
--- a/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj.filters
+++ b/build/Visual Studio 15 2017 Win64/ReactorLLVM.vcxproj.filters
@@ -7,6 +7,9 @@
     <ClCompile Include="$(SolutionDir)src\Reactor\LLVMReactor.cpp">

       <Filter>src\Reactor</Filter>

     </ClCompile>

+    <ClCompile Include="$(SolutionDir)src\Reactor\LLVMReactorDebugInfo.cpp">

+      <Filter>src\Reactor</Filter>

+    </ClCompile>

     <ClCompile Include="$(SolutionDir)src\Reactor\Routine.cpp">

       <Filter>src\Reactor</Filter>

     </ClCompile>

@@ -33,6 +36,12 @@
     <ClInclude Include="$(SolutionDir)src\Reactor\Routine.hpp">

       <Filter>src\Reactor</Filter>

     </ClInclude>

+    <ClInclude Include="$(SolutionDir)src\Reactor\LLVMReactor.hpp">

+      <Filter>src\Reactor</Filter>

+    </ClInclude>

+    <ClInclude Include="$(SolutionDir)src\Reactor\LLVMReactorDebugInfo.hpp">

+      <Filter>src\Reactor</Filter>

+    </ClInclude>

     <ClInclude Include="$(SolutionDir)src\Reactor\LLVMRoutine.hpp">

       <Filter>src\Reactor</Filter>

     </ClInclude>

diff --git a/docs/ReactorDebugInfo.md b/docs/ReactorDebugInfo.md
new file mode 100644
index 0000000..3b612d4
--- /dev/null
+++ b/docs/ReactorDebugInfo.md
@@ -0,0 +1,237 @@
+# Reactor Debug Info Generation
+
+## Introduction
+
+Reactor produces Just In Time compiled dynamic executable code and can be used to JIT high performance functions specialized for runtime
+configurations, or to even build a compiler.
+
+In order to debug executable code at a higher level than disassembly, source code files are required.
+
+Reactor has two potential sources of source code:
+
+1. The C++ source code of the program that calls into Reactor.
+2. External source files read by the program and passed to Reactor.
+
+While case (2) is preferable for implementing a compiler, this is currently not
+implemented.
+
+Reactor implements case (1) and this can be used by GDB to single line step and
+inspect variables.
+
+## Supported Platforms
+
+Currently:
+
+* Debug info generation is only supported on Linux with the LLVM 7
+backend.
+* GDB is the only supported debugger.
+* The program must be compiled with debug info iteself.
+
+## Enabling
+
+Debug generation is enabled with `REACTOR_EMIT_DEBUG_INFO` CMake flag (defaults
+to disabled).
+
+## Implementation details
+
+### Source Location
+
+All Reactor functions begin with a call to `RR_DEBUG_INFO_UPDATE_LOC()`, which calls into `rr::DebugInfo::EmitLocation()`.
+
+`rr::DebugInfo::EmitLocation()` calls `rr::DebugInfo::getCallerBacktrace()`,
+which in turn uses [`libbacktrace`](https://github.com/ianlancetaylor/libbacktrace)
+to unwind the stack and find the file, function and line of the caller.
+
+This information is passed to `llvm::IRBuilder<>::SetCurrentDebugLocation`
+to emit source line information for the next LLVM instructions to be built.
+
+### Variables
+
+There are 3 aspects to generating variable debug information:
+
+#### 1. Variable names
+
+Constructing a Reactor `LValue`:
+
+```C++
+rr::Int a = 1;
+```
+
+Will emit an LLVM `alloca` instruction to allocate the storage of the variable,
+and emit another to initialize it to the constant `1`. While fluent, none of the
+Reactor calls see the name of the C++ local variable "`a`", and the LLVM `alloca`
+value gets a meaningless numerical value.
+
+There are two potential ways that Reactor can obtain the variable name:
+
+1. Use the running executable's own debug information to examine the local
+   declaration and extract the local variable's name.
+2. Use the backtrace information to parse the name from the source file.
+
+While (1) is arguably a cleaner and more robust solution, (2) is
+easier to implement and can work for the majority of use cases.
+
+(2) is the current solution implemented.
+
+`rr::DebugInfo::getOrParseFileTokens()` scans a source file line by line, and
+uses a regular expression to look for patterns of `<type> <name>`. Matching is not
+precise, but is adequate to find locals constructed with and without assignment.
+
+#### 2. Variable binding
+
+Given that we can find a variable name for a given source line, we need a way of
+binding the LLVM values to the name.
+
+Given our trivial example:
+
+```C++
+rr::Int a = 1
+```
+
+The `rr::Int` constructor calls `RR_DEBUG_INFO_EMIT_VAR()` passing the storage
+value as single argument. `RR_DEBUG_INFO_EMIT_VAR()` performs the backtrace
+to find the source file and line and uses the token information produced by
+`rr::DebugInfo::getOrParseFileTokens()` to identify the variable name.
+
+However, things get a bit more complicated when there are multiple variables
+being constructed on the same line.
+
+Take for example:
+
+```C++
+rr::Int a = rr::Int(1) + rr::Int(2)
+```
+
+Here we have 3 calls to the `rr::Int` constructor, each calling down
+to `RR_DEBUG_INFO_EMIT_VAR()`.
+
+To disambiguate which of these should be bound to the variable name "`a`",
+`rr::DebugInfo::EmitVariable()` buffers the binding into
+`scope.pending` and the last binding for a given line is used by
+`DebugInfo::emitPending()`. For variable construction and assignment, C++
+guarantees that the LHS is the last value to be constructed.
+
+This solution is not perfect.
+
+Multi-line expressions, multiple assignments on a single line, macro obfuscation
+can all break variable bindings - however the majority of typical cases work.
+
+#### 3. Variable scope
+
+`rr::DebugInfo` maintains a stack of `llvm::DIScope`s and `llvm::DILocation`s
+that mirrors the current backtrace for function being called.
+
+A synthetic call stack is produced by chaining `llvm::DILocation`s with
+`InlinedAt`s.
+
+For example, at the declaration of `i`:
+
+```C++
+void B()
+{
+    rr::Int i; // <- here
+}
+
+void A()
+{
+    B();
+}
+
+int main(int argc, const char* argv[])
+{
+    A();
+}
+```
+
+The `DIScope` hierarchy would be:
+
+```C++
+                              DIFile: "foo.cpp"
+rr::DebugInfo::diScope[0].di: ↳ DISubprogram: "main"
+rr::DebugInfo::diScope[1].di: ↳ DISubprogram: "A"
+rr::DebugInfo::diScope[2].di: ↳ DISubprogram: "B"
+```
+
+The `DILocation` hierarchy would be:
+
+```C++
+rr::DebugInfo::diRootLocation:      DILocation(DISubprogram: "ReactorFunction")
+rr::DebugInfo::diScope[0].location: ↳ DILocation(DISubprogram: "main")
+rr::DebugInfo::diScope[1].location:   ↳ DILocation(DISubprogram: "A")
+rr::DebugInfo::diScope[2].location:     ↳ DILocation(DISubprogram: "B")
+```
+
+Where '↳' represents an `InlinedAt`.
+
+
+`rr::DebugInfo::diScope` is updated by `rr::DebugInfo::syncScope()`.
+
+`llvm::DIScope`s typically do not nest - there is usually a separate
+`llvm::DISubprogram` for each function in the callstack. All local variables
+within a function will typically share the same scope, regardless of whether
+they are declared within a sub-block.
+
+Loops and jumps within a function add complexity. Consider:
+
+```C++
+void B()
+{
+    rr::Int i = 0;
+}
+
+void A()
+{
+    for (int i = 0; i < 3; i++)
+    {
+        rr::Int x = 0;
+    }
+    B();
+}
+
+int main(int argc, const char* argv[])
+{
+    A();
+}
+```
+
+In this particular example Reactor will not be aware of the `for` loop, and will
+attempt to create three variables called "`x`" in the same function scope for `A()`.
+Duplicate symbols in the same `llvm::DIScope` result in undefined behavior.
+
+To solve this, `rr::DebugInfo::syncScope()` observes when a function jumps
+backwards, and forks the current `llvm::DILexicalBlock` for the function. This
+results in a number of `llvm::DILexicalBlock` chains, each declaring variables
+that shadow the previous block.
+
+At the declaration of `i`, the `DIScope` hierarchy would be:
+
+```C++
+                              DIFile: "foo.cpp"
+rr::DebugInfo::diScope[0].di: ↳ DISubprogram: "main"
+                              ↳ DISubprogram: "A"
+                              | ↳ DILexicalBlock: "A".1
+rr::DebugInfo::diScope[1].di: |   ↳ DILexicalBlock: "A".2
+rr::DebugInfo::diScope[2].di: ↳ DISubprogram: "B"
+```
+
+The `DILocation` hierarchy would be:
+
+```C++
+rr::DebugInfo::diRootLocation:      DILocation(DISubprogram: "ReactorFunction")
+rr::DebugInfo::diScope[0].location: ↳ DILocation(DISubprogram: "main")
+rr::DebugInfo::diScope[1].location:   ↳ DILocation(DILexicalBlock: "A".2)
+rr::DebugInfo::diScope[2].location:     ↳ DILocation(DISubprogram: "B")
+```
+
+### Debugger integration
+
+Once the debug information has been generated, it needs to be handed to the
+debugger.
+
+Reactor uses [`llvm::JITEventListener::createGDBRegistrationListener()`](http://llvm.org/doxygen/classllvm_1_1JITEventListener.html#a004abbb5a0d48ac376dfbe3e3c97c306)
+to inform GDB of the JIT'd program and its debugging information.
+More information [can be found here](https://llvm.org/docs/DebuggingJITedCode.html).
+
+LLDB should be able to support this same mechanism, but at the time of writing
+this does not appear to work.
+
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 9c453b7..6c30207 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -14,6 +14,8 @@
 
 #include "Reactor.hpp"
 #include "Debug.hpp"
+#include "LLVMReactor.hpp"
+#include "LLVMReactorDebugInfo.hpp"
 
 #include "x86.hpp"
 #include "CPUID.hpp"
@@ -117,6 +119,10 @@
 	llvm::Module *module = nullptr;
 	llvm::Function *function = nullptr;
 
+#ifdef ENABLE_RR_DEBUG_INFO
+	std::unique_ptr<rr::DebugInfo> debugInfo;
+#endif
+
 	rr::MutexLock codegenMutex;
 
 #ifdef ENABLE_RR_PRINT
@@ -555,6 +561,9 @@
 	public:
 		ExternalFunctionSymbolResolver()
 		{
+			struct F { static void nop() {} };
+			func_.emplace("nop", reinterpret_cast<void*>(F::nop));
+
 			func_.emplace("floorf", reinterpret_cast<void*>(floorf));
 			func_.emplace("nearbyintf", reinterpret_cast<void*>(nearbyintf));
 			func_.emplace("truncf", reinterpret_cast<void*>(truncf));
@@ -639,6 +648,9 @@
 					}
 				})),
 			targetMachine(llvm::EngineBuilder()
+#ifdef ENABLE_RR_DEBUG_INFO
+				.setOptLevel(llvm::CodeGenOpt::None)
+#endif // ENABLE_RR_DEBUG_INFO
 				.setMArch(arch)
 				.setMAttrs(mattrs)
 				.setTargetOptions(targetOpts)
@@ -650,7 +662,25 @@
 					return ObjLayer::Resources{
 						std::make_shared<llvm::SectionMemoryManager>(),
 						resolver};
-				}),
+				},
+				ObjLayer::NotifyLoadedFtor(),
+				[](llvm::orc::VModuleKey, const llvm::object::ObjectFile &Obj, const llvm::RuntimeDyld::LoadedObjectInfo &L) {
+#ifdef ENABLE_RR_DEBUG_INFO
+					if (debugInfo != nullptr)
+					{
+						debugInfo->NotifyObjectEmitted(Obj, L);
+					}
+#endif // ENABLE_RR_DEBUG_INFO
+				},
+				[](llvm::orc::VModuleKey, const llvm::object::ObjectFile &Obj) {
+#ifdef ENABLE_RR_DEBUG_INFO
+					if (debugInfo != nullptr)
+					{
+						debugInfo->NotifyFreeingObject(Obj);
+					}
+#endif // ENABLE_RR_DEBUG_INFO
+				}
+	  		),
 			compileLayer(objLayer, llvm::orc::SimpleCompiler(*targetMachine)),
 			emittedFunctionsNum(0)
 		{
@@ -701,6 +731,13 @@
 
 		void optimize(llvm::Module *module)
 		{
+#ifdef ENABLE_RR_DEBUG_INFO
+			if (debugInfo != nullptr)
+			{
+				return; // Don't optimize if we're generating debug info.
+			}
+#endif // ENABLE_RR_DEBUG_INFO
+
 			std::unique_ptr<llvm::legacy::PassManager> passManager(
 				new llvm::legacy::PassManager());
 
@@ -787,26 +824,11 @@
 		}
 	}
 
-	inline Type *T(llvm::Type *t)
-	{
-		return reinterpret_cast<Type*>(t);
-	}
-
 	Type *T(InternalType t)
 	{
 		return reinterpret_cast<Type*>(t);
 	}
 
-	inline llvm::Value *V(Value *t)
-	{
-		return reinterpret_cast<llvm::Value*>(t);
-	}
-
-	inline Value *V(llvm::Value *t)
-	{
-		return reinterpret_cast<Value*>(t);
-	}
-
 	inline std::vector<llvm::Type*> &T(std::vector<Type*> &t)
 	{
 		return reinterpret_cast<std::vector<llvm::Type*>&>(t);
@@ -1038,6 +1060,13 @@
 			::module->print(file, 0);
 		}
 
+#ifdef ENABLE_RR_DEBUG_INFO
+		if (debugInfo != nullptr)
+		{
+			debugInfo->Finalize();
+		}
+#endif // ENABLE_RR_DEBUG_INFO
+
 		LLVMRoutine *routine = ::reactorJIT->acquireRoutine(::function);
 
 		return routine;
@@ -1113,6 +1142,10 @@
 			::function->addFnAttr("stack-probe-size", "1048576");
 		#endif
 
+#ifdef ENABLE_RR_DEBUG_INFO
+		::debugInfo = std::unique_ptr<DebugInfo>(new DebugInfo(::builder, ::context, ::module, ::function));
+#endif // ENABLE_RR_DEBUG_INFO
+
 		::builder->SetInsertPoint(llvm::BasicBlock::Create(*::context, "", ::function));
 	}
 
@@ -1131,6 +1164,8 @@
 
 	void Nucleus::createRetVoid()
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
+
 		// Code generated after this point is unreachable, so any variables
 		// being read can safely return an undefined value. We have to avoid
 		// materializing variables after the terminator ret instruction.
@@ -1141,6 +1176,8 @@
 
 	void Nucleus::createRet(Value *v)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
+
 		// Code generated after this point is unreachable, so any variables
 		// being read can safely return an undefined value. We have to avoid
 		// materializing variables after the terminator ret instruction.
@@ -1151,6 +1188,7 @@
 
 	void Nucleus::createBr(BasicBlock *dest)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Variable::materializeAll();
 
 		::builder->CreateBr(B(dest));
@@ -1158,118 +1196,140 @@
 
 	void Nucleus::createCondBr(Value *cond, BasicBlock *ifTrue, BasicBlock *ifFalse)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Variable::materializeAll();
-
 		::builder->CreateCondBr(V(cond), B(ifTrue), B(ifFalse));
 	}
 
 	Value *Nucleus::createAdd(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateAdd(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createSub(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateSub(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createMul(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateMul(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createUDiv(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateUDiv(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createSDiv(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateSDiv(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFAdd(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFAdd(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFSub(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFSub(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFMul(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFMul(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFDiv(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFDiv(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createURem(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateURem(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createSRem(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateSRem(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFRem(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFRem(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createShl(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateShl(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createLShr(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateLShr(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createAShr(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateAShr(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createAnd(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateAnd(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createOr(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateOr(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createXor(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateXor(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createNeg(Value *v)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateNeg(V(v)));
 	}
 
 	Value *Nucleus::createFNeg(Value *v)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFNeg(V(v)));
 	}
 
 	Value *Nucleus::createNot(Value *v)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateNot(V(v)));
 	}
 
 	Value *Nucleus::createLoad(Value *ptr, Type *type, bool isVolatile, unsigned int alignment, bool atomic, std::memory_order memoryOrder)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		switch(asInternalType(type))
 		{
 		case Type_v2i32:
@@ -1309,6 +1369,7 @@
 
 	Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatile, unsigned int alignment, bool atomic, std::memory_order memoryOrder)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		switch(asInternalType(type))
 		{
 		case Type_v2i32:
@@ -1348,8 +1409,8 @@
 
 	Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		ASSERT(V(ptr)->getType()->getContainedType(0) == T(type));
-
 		if(sizeof(void*) == 8)
 		{
 			// LLVM manual: "When indexing into an array, pointer or vector,
@@ -1392,46 +1453,55 @@
 
 	Value *Nucleus::createAtomicAdd(Value *ptr, Value *value)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateAtomicRMW(llvm::AtomicRMWInst::Add, V(ptr), V(value), llvm::AtomicOrdering::SequentiallyConsistent));
 	}
 
 	Value *Nucleus::createTrunc(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateTrunc(V(v), T(destType)));
 	}
 
 	Value *Nucleus::createZExt(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateZExt(V(v), T(destType)));
 	}
 
 	Value *Nucleus::createSExt(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateSExt(V(v), T(destType)));
 	}
 
 	Value *Nucleus::createFPToSI(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFPToSI(V(v), T(destType)));
 	}
 
 	Value *Nucleus::createSIToFP(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateSIToFP(V(v), T(destType)));
 	}
 
 	Value *Nucleus::createFPTrunc(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFPTrunc(V(v), T(destType)));
 	}
 
 	Value *Nucleus::createFPExt(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFPExt(V(v), T(destType)));
 	}
 
 	Value *Nucleus::createBitCast(Value *v, Type *destType)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// Bitcasts must be between types of the same logical size. But with emulated narrow vectors we need
 		// support for casting between scalars and wide vectors. Emulate them by writing to the stack and
 		// reading back as the destination type.
@@ -1455,137 +1525,165 @@
 
 	Value *Nucleus::createICmpEQ(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpEQ(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpNE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpNE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpUGT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpUGT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpUGE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpUGE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpULT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpULT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpULE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpULE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpSGT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpSGT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpSGE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpSGE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpSLT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpSLT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createICmpSLE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateICmpSLE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpOEQ(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpOEQ(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpOGT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpOGT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpOGE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpOGE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpOLT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpOLT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpOLE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpOLE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpONE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpONE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpORD(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpORD(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpUNO(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpUNO(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpUEQ(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpUEQ(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpUGT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpUGT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpUGE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpUGE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpULT(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpULT(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpULE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpULE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createFCmpUNE(Value *lhs, Value *rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateFCmpUNE(V(lhs), V(rhs)));
 	}
 
 	Value *Nucleus::createExtractElement(Value *vector, Type *type, int index)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		ASSERT(V(vector)->getType()->getContainedType(0) == T(type));
 		return V(::builder->CreateExtractElement(V(vector), V(createConstantInt(index))));
 	}
 
 	Value *Nucleus::createInsertElement(Value *vector, Value *element, int index)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateInsertElement(V(vector), V(element), V(createConstantInt(index))));
 	}
 
 	Value *Nucleus::createShuffleVector(Value *v1, Value *v2, const int *select)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
+
 		int size = llvm::cast<llvm::VectorType>(V(v1)->getType())->getNumElements();
 		const int maxSize = 16;
 		llvm::Constant *swizzle[maxSize];
@@ -1603,22 +1701,26 @@
 
 	Value *Nucleus::createSelect(Value *c, Value *ifTrue, Value *ifFalse)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(::builder->CreateSelect(V(c), V(ifTrue), V(ifFalse)));
 	}
 
 	SwitchCases *Nucleus::createSwitch(Value *control, BasicBlock *defaultBranch, unsigned numCases)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return reinterpret_cast<SwitchCases*>(::builder->CreateSwitch(V(control), B(defaultBranch), numCases));
 	}
 
 	void Nucleus::addSwitchCase(SwitchCases *switchCases, int label, BasicBlock *branch)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		llvm::SwitchInst *sw = reinterpret_cast<llvm::SwitchInst *>(switchCases);
 		sw->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*::context), label, true), B(branch));
 	}
 
 	void Nucleus::createUnreachable()
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		::builder->CreateUnreachable();
 	}
 
@@ -1629,56 +1731,67 @@
 
 	Value *Nucleus::createNullValue(Type *Ty)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::Constant::getNullValue(T(Ty)));
 	}
 
 	Value *Nucleus::createConstantLong(int64_t i)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt64Ty(*::context), i, true));
 	}
 
 	Value *Nucleus::createConstantInt(int i)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*::context), i, true));
 	}
 
 	Value *Nucleus::createConstantInt(unsigned int i)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*::context), i, false));
 	}
 
 	Value *Nucleus::createConstantBool(bool b)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt1Ty(*::context), b));
 	}
 
 	Value *Nucleus::createConstantByte(signed char i)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt8Ty(*::context), i, true));
 	}
 
 	Value *Nucleus::createConstantByte(unsigned char i)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt8Ty(*::context), i, false));
 	}
 
 	Value *Nucleus::createConstantShort(short i)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt16Ty(*::context), i, true));
 	}
 
 	Value *Nucleus::createConstantShort(unsigned short i)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantInt::get(llvm::Type::getInt16Ty(*::context), i, false));
 	}
 
 	Value *Nucleus::createConstantFloat(float x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantFP::get(T(Float::getType()), x));
 	}
 
 	Value *Nucleus::createNullPointer(Type *Ty)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return V(llvm::ConstantPointerNull::get(llvm::PointerType::get(T(Ty), 0)));
 	}
 
@@ -1756,6 +1869,7 @@
 
 	RValue<Byte8> AddSat(RValue<Byte8> x, RValue<Byte8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::paddusb(x, y);
 #else
@@ -1765,6 +1879,7 @@
 
 	RValue<Byte8> SubSat(RValue<Byte8> x, RValue<Byte8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psubusb(x, y);
 #else
@@ -1774,6 +1889,7 @@
 
 	RValue<Int> SignMask(RValue<Byte8> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmovmskb(x);
 #else
@@ -1792,6 +1908,7 @@
 
 	RValue<Byte8> CmpEQ(RValue<Byte8> x, RValue<Byte8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pcmpeqb(x, y);
 #else
@@ -1806,6 +1923,7 @@
 
 	RValue<SByte8> AddSat(RValue<SByte8> x, RValue<SByte8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::paddsb(x, y);
 #else
@@ -1815,6 +1933,7 @@
 
 	RValue<SByte8> SubSat(RValue<SByte8> x, RValue<SByte8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psubsb(x, y);
 #else
@@ -1824,6 +1943,7 @@
 
 	RValue<Int> SignMask(RValue<SByte8> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmovmskb(As<Byte8>(x));
 #else
@@ -1833,6 +1953,7 @@
 
 	RValue<Byte8> CmpGT(RValue<SByte8> x, RValue<SByte8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pcmpgtb(x, y);
 #else
@@ -1842,6 +1963,7 @@
 
 	RValue<Byte8> CmpEQ(RValue<SByte8> x, RValue<SByte8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pcmpeqb(As<Byte8>(x), As<Byte8>(y));
 #else
@@ -1876,6 +1998,7 @@
 
 	Short4::Short4(RValue<Int4> cast)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		int select[8] = {0, 2, 4, 6, 0, 2, 4, 6};
 		Value *short8 = Nucleus::createBitCast(cast.value, Short8::getType());
 
@@ -1891,6 +2014,7 @@
 
 	Short4::Short4(RValue<Float4> cast)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Int4 v4i32 = Int4(cast);
 #if defined(__i386__) || defined(__x86_64__)
 		v4i32 = As<Int4>(x86::packssdw(v4i32, v4i32));
@@ -1904,6 +2028,7 @@
 
 	RValue<Short4> operator<<(RValue<Short4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 	//	return RValue<Short4>(Nucleus::createShl(lhs.value, rhs.value));
 
@@ -1915,6 +2040,7 @@
 
 	RValue<Short4> operator>>(RValue<Short4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psraw(lhs, rhs);
 #else
@@ -1924,6 +2050,7 @@
 
 	RValue<Short4> Max(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmaxsw(x, y);
 #else
@@ -1933,6 +2060,7 @@
 
 	RValue<Short4> Min(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pminsw(x, y);
 #else
@@ -1942,6 +2070,7 @@
 
 	RValue<Short4> AddSat(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::paddsw(x, y);
 #else
@@ -1951,6 +2080,7 @@
 
 	RValue<Short4> SubSat(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psubsw(x, y);
 #else
@@ -1960,6 +2090,7 @@
 
 	RValue<Short4> MulHigh(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmulhw(x, y);
 #else
@@ -1969,6 +2100,7 @@
 
 	RValue<Int2> MulAdd(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmaddwd(x, y);
 #else
@@ -1978,6 +2110,7 @@
 
 	RValue<SByte8> PackSigned(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		auto result = x86::packsswb(x, y);
 #else
@@ -1988,6 +2121,7 @@
 
 	RValue<Byte8> PackUnsigned(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		auto result = x86::packuswb(x, y);
 #else
@@ -1998,6 +2132,7 @@
 
 	RValue<Short4> CmpGT(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pcmpgtw(x, y);
 #else
@@ -2007,6 +2142,7 @@
 
 	RValue<Short4> CmpEQ(RValue<Short4> x, RValue<Short4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pcmpeqw(x, y);
 #else
@@ -2021,6 +2157,7 @@
 
 	UShort4::UShort4(RValue<Float4> cast, bool saturate)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		if(saturate)
 		{
 #if defined(__i386__) || defined(__x86_64__)
@@ -2043,6 +2180,7 @@
 
 	RValue<UShort4> operator<<(RValue<UShort4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 	//	return RValue<Short4>(Nucleus::createShl(lhs.value, rhs.value));
 
@@ -2054,6 +2192,7 @@
 
 	RValue<UShort4> operator>>(RValue<UShort4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 	//	return RValue<Short4>(Nucleus::createLShr(lhs.value, rhs.value));
 
@@ -2065,16 +2204,19 @@
 
 	RValue<UShort4> Max(RValue<UShort4> x, RValue<UShort4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<UShort4>(Max(As<Short4>(x) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u), As<Short4>(y) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u)) + Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u));
 	}
 
 	RValue<UShort4> Min(RValue<UShort4> x, RValue<UShort4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<UShort4>(Min(As<Short4>(x) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u), As<Short4>(y) - Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u)) + Short4(0x8000u, 0x8000u, 0x8000u, 0x8000u));
 	}
 
 	RValue<UShort4> AddSat(RValue<UShort4> x, RValue<UShort4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::paddusw(x, y);
 #else
@@ -2084,6 +2226,7 @@
 
 	RValue<UShort4> SubSat(RValue<UShort4> x, RValue<UShort4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psubusw(x, y);
 #else
@@ -2093,6 +2236,7 @@
 
 	RValue<UShort4> MulHigh(RValue<UShort4> x, RValue<UShort4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmulhuw(x, y);
 #else
@@ -2102,6 +2246,7 @@
 
 	RValue<UShort4> Average(RValue<UShort4> x, RValue<UShort4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pavgw(x, y);
 #else
@@ -2116,6 +2261,7 @@
 
 	RValue<Short8> operator<<(RValue<Short8> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psllw(lhs, rhs);
 #else
@@ -2125,6 +2271,7 @@
 
 	RValue<Short8> operator>>(RValue<Short8> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psraw(lhs, rhs);
 #else
@@ -2134,6 +2281,7 @@
 
 	RValue<Int4> MulAdd(RValue<Short8> x, RValue<Short8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmaddwd(x, y);
 #else
@@ -2143,6 +2291,7 @@
 
 	RValue<Short8> MulHigh(RValue<Short8> x, RValue<Short8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmulhw(x, y);
 #else
@@ -2157,6 +2306,7 @@
 
 	RValue<UShort8> operator<<(RValue<UShort8> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return As<UShort8>(x86::psllw(As<Short8>(lhs), rhs));
 #else
@@ -2166,6 +2316,7 @@
 
 	RValue<UShort8> operator>>(RValue<UShort8> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psrlw(lhs, rhs);   // FIXME: Fallback required
 #else
@@ -2175,6 +2326,7 @@
 
 	RValue<UShort8> Swizzle(RValue<UShort8> x, char select0, char select1, char select2, char select3, char select4, char select5, char select6, char select7)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		int pshufb[16] =
 		{
 			select0 + 0,
@@ -2204,6 +2356,7 @@
 
 	RValue<UShort8> MulHigh(RValue<UShort8> x, RValue<UShort8> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pmulhuw(x, y);
 #else
@@ -2218,6 +2371,7 @@
 
 	RValue<Int> operator++(Int &val, int)   // Post-increment
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		RValue<Int> res = val;
 
 		Value *inc = Nucleus::createAdd(res.value, Nucleus::createConstantInt(1));
@@ -2228,6 +2382,7 @@
 
 	const Int &operator++(Int &val)   // Pre-increment
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *inc = Nucleus::createAdd(val.loadValue(), Nucleus::createConstantInt(1));
 		val.storeValue(inc);
 
@@ -2236,6 +2391,7 @@
 
 	RValue<Int> operator--(Int &val, int)   // Post-decrement
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		RValue<Int> res = val;
 
 		Value *inc = Nucleus::createSub(res.value, Nucleus::createConstantInt(1));
@@ -2246,6 +2402,7 @@
 
 	const Int &operator--(Int &val)   // Pre-decrement
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *inc = Nucleus::createSub(val.loadValue(), Nucleus::createConstantInt(1));
 		val.storeValue(inc);
 
@@ -2254,6 +2411,7 @@
 
 	RValue<Int> RoundInt(RValue<Float> cast)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::cvtss2si(cast);
 #else
@@ -2273,6 +2431,7 @@
 
 	UInt::UInt(RValue<Float> cast)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// Note: createFPToUI is broken, must perform conversion using createFPtoSI
 		// Value *integer = Nucleus::createFPToUI(cast.value, UInt::getType());
 
@@ -2292,6 +2451,7 @@
 
 	RValue<UInt> operator++(UInt &val, int)   // Post-increment
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		RValue<UInt> res = val;
 
 		Value *inc = Nucleus::createAdd(res.value, Nucleus::createConstantInt(1));
@@ -2302,6 +2462,7 @@
 
 	const UInt &operator++(UInt &val)   // Pre-increment
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *inc = Nucleus::createAdd(val.loadValue(), Nucleus::createConstantInt(1));
 		val.storeValue(inc);
 
@@ -2310,6 +2471,7 @@
 
 	RValue<UInt> operator--(UInt &val, int)   // Post-decrement
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		RValue<UInt> res = val;
 
 		Value *inc = Nucleus::createSub(res.value, Nucleus::createConstantInt(1));
@@ -2320,6 +2482,7 @@
 
 	const UInt &operator--(UInt &val)   // Pre-decrement
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *inc = Nucleus::createSub(val.loadValue(), Nucleus::createConstantInt(1));
 		val.storeValue(inc);
 
@@ -2353,6 +2516,7 @@
 
 	RValue<Int2> operator<<(RValue<Int2> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 	//	return RValue<Int2>(Nucleus::createShl(lhs.value, rhs.value));
 
@@ -2364,6 +2528,7 @@
 
 	RValue<Int2> operator>>(RValue<Int2> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 	//	return RValue<Int2>(Nucleus::createAShr(lhs.value, rhs.value));
 
@@ -2380,6 +2545,7 @@
 
 	RValue<UInt2> operator<<(RValue<UInt2> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 	//	return RValue<UInt2>(Nucleus::createShl(lhs.value, rhs.value));
 
@@ -2391,6 +2557,7 @@
 
 	RValue<UInt2> operator>>(RValue<UInt2> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 	//	return RValue<UInt2>(Nucleus::createLShr(lhs.value, rhs.value));
 
@@ -2407,6 +2574,7 @@
 
 	Int4::Int4(RValue<Byte4> cast) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2429,6 +2597,7 @@
 
 	Int4::Int4(RValue<SByte4> cast) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2451,6 +2620,7 @@
 
 	Int4::Int4(RValue<Short4> cast) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2467,6 +2637,7 @@
 
 	Int4::Int4(RValue<UShort4> cast) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2483,6 +2654,7 @@
 
 	Int4::Int4(RValue<Int> rhs) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *vector = loadValue();
 		Value *insert = Nucleus::createInsertElement(vector, rhs.value, 0);
 
@@ -2494,6 +2666,7 @@
 
 	RValue<Int4> operator<<(RValue<Int4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::pslld(lhs, rhs);
 #else
@@ -2503,6 +2676,7 @@
 
 	RValue<Int4> operator>>(RValue<Int4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psrad(lhs, rhs);
 #else
@@ -2512,6 +2686,7 @@
 
 	RValue<Int4> CmpEQ(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpEQ(x.value, y.value), Int4::getType()));
@@ -2520,6 +2695,7 @@
 
 	RValue<Int4> CmpLT(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSLT(x.value, y.value), Int4::getType()));
@@ -2528,6 +2704,7 @@
 
 	RValue<Int4> CmpLE(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSLE(x.value, y.value), Int4::getType()));
@@ -2536,6 +2713,7 @@
 
 	RValue<Int4> CmpNEQ(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpNE(x.value, y.value), Int4::getType()));
@@ -2544,6 +2722,7 @@
 
 	RValue<Int4> CmpNLT(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSGE(x.value, y.value), Int4::getType()));
@@ -2552,6 +2731,7 @@
 
 	RValue<Int4> CmpNLE(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<Int4>(Nucleus::createSExt(Nucleus::createICmpSGT(x.value, y.value), Int4::getType()));
@@ -2560,6 +2740,7 @@
 
 	RValue<Int4> Max(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2575,6 +2756,7 @@
 
 	RValue<Int4> Min(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2590,6 +2772,7 @@
 
 	RValue<Int4> RoundInt(RValue<Float4> cast)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::cvtps2dq(cast);
 #else
@@ -2599,18 +2782,21 @@
 
 	RValue<Int4> MulHigh(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// TODO: For x86, build an intrinsics version of this which uses shuffles + pmuludq.
 		return As<Int4>(V(lowerMulHigh(V(x.value), V(y.value), true)));
 	}
 
 	RValue<UInt4> MulHigh(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// TODO: For x86, build an intrinsics version of this which uses shuffles + pmuludq.
 		return As<UInt4>(V(lowerMulHigh(V(x.value), V(y.value), false)));
 	}
 
 	RValue<Short8> PackSigned(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::packssdw(x, y);
 #else
@@ -2620,6 +2806,7 @@
 
 	RValue<UShort8> PackUnsigned(RValue<Int4> x, RValue<Int4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::packusdw(x, y);
 #else
@@ -2629,6 +2816,7 @@
 
 	RValue<Int> SignMask(RValue<Int4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::movmskps(As<Float4>(x));
 #else
@@ -2643,6 +2831,7 @@
 
 	UInt4::UInt4(RValue<Float4> cast) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// Note: createFPToUI is broken, must perform conversion using createFPtoSI
 		// Value *xyzw = Nucleus::createFPToUI(cast.value, UInt4::getType());
 
@@ -2662,6 +2851,7 @@
 
 	RValue<UInt4> operator<<(RValue<UInt4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return As<UInt4>(x86::pslld(As<Int4>(lhs), rhs));
 #else
@@ -2671,6 +2861,7 @@
 
 	RValue<UInt4> operator>>(RValue<UInt4> lhs, unsigned char rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::psrld(lhs, rhs);
 #else
@@ -2680,6 +2871,7 @@
 
 	RValue<UInt4> CmpEQ(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpEQ(x.value, y.value), Int4::getType()));
@@ -2688,11 +2880,13 @@
 
 	RValue<UInt4> CmpLT(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpULT(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<UInt4> CmpLE(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpULE(x.value, y.value), Int4::getType()));
@@ -2701,11 +2895,13 @@
 
 	RValue<UInt4> CmpNEQ(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpNE(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<UInt4> CmpNLT(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		// FIXME: An LLVM bug causes SExt(ICmpCC()) to produce 0 or 1 instead of 0 or ~0
 		//        Restore the following line when LLVM is updated to a version where this issue is fixed.
 		// return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpUGE(x.value, y.value), Int4::getType()));
@@ -2714,11 +2910,13 @@
 
 	RValue<UInt4> CmpNLE(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<UInt4>(Nucleus::createSExt(Nucleus::createICmpUGT(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<UInt4> Max(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2734,6 +2932,7 @@
 
 	RValue<UInt4> Min(RValue<UInt4> x, RValue<UInt4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2759,6 +2958,7 @@
 
 	RValue<Float> Rcp_pp(RValue<Float> x, bool exactAtPow2)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(exactAtPow2)
 		{
@@ -2774,6 +2974,7 @@
 
 	RValue<Float> RcpSqrt_pp(RValue<Float> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::rsqrtss(x);
 #else
@@ -2783,6 +2984,7 @@
 
 	RValue<Float> Sqrt(RValue<Float> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::sqrtss(x);
 #else
@@ -2792,6 +2994,7 @@
 
 	RValue<Float> Round(RValue<Float> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2808,6 +3011,7 @@
 
 	RValue<Float> Trunc(RValue<Float> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2824,6 +3028,7 @@
 
 	RValue<Float> Frac(RValue<Float> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2842,6 +3047,7 @@
 
 	RValue<Float> Floor(RValue<Float> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2858,6 +3064,7 @@
 
 	RValue<Float> Ceil(RValue<Float> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -2882,6 +3089,7 @@
 
 	Float4::Float4(RValue<Float> rhs) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *vector = loadValue();
 		Value *insert = Nucleus::createInsertElement(vector, rhs.value, 0);
 
@@ -2893,6 +3101,7 @@
 
 	RValue<Float4> Max(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::maxps(x, y);
 #else
@@ -2902,6 +3111,7 @@
 
 	RValue<Float4> Min(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::minps(x, y);
 #else
@@ -2911,6 +3121,7 @@
 
 	RValue<Float4> Rcp_pp(RValue<Float4> x, bool exactAtPow2)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(exactAtPow2)
 		{
@@ -2926,6 +3137,7 @@
 
 	RValue<Float4> RcpSqrt_pp(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::rsqrtps(x);
 #else
@@ -2935,6 +3147,7 @@
 
 	RValue<Float4> Sqrt(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::sqrtps(x);
 #else
@@ -2944,6 +3157,7 @@
 
 	RValue<Int> SignMask(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		return x86::movmskps(x);
 #else
@@ -2953,72 +3167,85 @@
 
 	RValue<Int4> CmpEQ(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 	//	return As<Int4>(x86::cmpeqps(x, y));
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOEQ(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpLT(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 	//	return As<Int4>(x86::cmpltps(x, y));
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOLT(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpLE(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 	//	return As<Int4>(x86::cmpleps(x, y));
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOLE(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpNEQ(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 	//	return As<Int4>(x86::cmpneqps(x, y));
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpONE(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpNLT(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 	//	return As<Int4>(x86::cmpnltps(x, y));
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOGE(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpNLE(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 	//	return As<Int4>(x86::cmpnleps(x, y));
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOGT(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUEQ(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULT(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULE(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUNE(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGE(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGT(x.value, y.value), Int4::getType()));
 	}
 
 	RValue<Float4> Round(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -3035,6 +3262,7 @@
 
 	RValue<Float4> Trunc(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -3051,6 +3279,7 @@
 
 	RValue<Float4> Frac(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Float4 frc;
 
 #if defined(__i386__) || defined(__x86_64__)
@@ -3075,6 +3304,7 @@
 
 	RValue<Float4> Floor(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -3091,6 +3321,7 @@
 
 	RValue<Float4> Ceil(RValue<Float4> x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 #if defined(__i386__) || defined(__x86_64__)
 		if(CPUID::supportsSSE4_1())
 		{
@@ -3267,6 +3498,7 @@
 
 	RValue<Long> Ticks()
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		llvm::Function *rdtsc = llvm::Intrinsic::getDeclaration(::module, llvm::Intrinsic::readcyclecounter);
 
 		return RValue<Long>(V(::builder->CreateCall(rdtsc)));
@@ -3935,4 +4167,48 @@
 	}
 #endif // ENABLE_RR_PRINT
 
+	void Break()
+	{
+		auto trap = ::llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::trap);
+		builder->CreateCall(trap);
+	}
+
+	void Nop()
+	{
+		auto voidTy = ::llvm::Type::getVoidTy(*context);
+		auto funcTy = ::llvm::FunctionType::get(voidTy, {}, false);
+		auto func = ::module->getOrInsertFunction("nop", funcTy);
+		builder->CreateCall(func);
+	}
+
+	void EmitDebugLocation()
+	{
+#ifdef ENABLE_RR_DEBUG_INFO
+		if (debugInfo != nullptr)
+		{
+			debugInfo->EmitLocation();
+		}
+#endif // ENABLE_RR_DEBUG_INFO
+	}
+
+	void EmitDebugVariable(Value* value)
+	{
+#ifdef ENABLE_RR_DEBUG_INFO
+		if (debugInfo != nullptr)
+		{
+			debugInfo->EmitVariable(value);
+		}
+#endif // ENABLE_RR_DEBUG_INFO
+	}
+
+	void FlushDebug()
+	{
+#ifdef ENABLE_RR_DEBUG_INFO
+		if (debugInfo != nullptr)
+		{
+			debugInfo->Flush();
+		}
+#endif // ENABLE_RR_DEBUG_INFO
+	}
+
 }
diff --git a/src/Reactor/LLVMReactor.hpp b/src/Reactor/LLVMReactor.hpp
new file mode 100644
index 0000000..4ff5274
--- /dev/null
+++ b/src/Reactor/LLVMReactor.hpp
@@ -0,0 +1,52 @@
+// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef rr_LLVMReactor_hpp
+#define rr_LLVMReactor_hpp
+
+namespace llvm
+{
+	class Type;
+	class Value;
+}
+
+namespace rr
+{
+	class Type;
+	class Value;
+
+	llvm::Type *T(Type *t);
+
+	inline Type *T(llvm::Type *t)
+	{
+		return reinterpret_cast<Type*>(t);
+	}
+
+	inline llvm::Value *V(Value *t)
+	{
+		return reinterpret_cast<llvm::Value*>(t);
+	}
+
+	inline Value *V(llvm::Value *t)
+	{
+		return reinterpret_cast<Value*>(t);
+	}
+
+	// Emits a no-op instruction that will not be optimized away.
+	// Useful for emitting something that can have a source location without
+	// effect.
+	void Nop();
+}
+
+#endif // rr_LLVMReactor_hpp
diff --git a/src/Reactor/LLVMReactorDebugInfo.cpp b/src/Reactor/LLVMReactorDebugInfo.cpp
new file mode 100644
index 0000000..75b4a03
--- /dev/null
+++ b/src/Reactor/LLVMReactorDebugInfo.cpp
@@ -0,0 +1,543 @@
+// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "LLVMReactorDebugInfo.hpp"
+
+#ifdef ENABLE_RR_DEBUG_INFO
+
+#include "Reactor.hpp"
+#include "LLVMReactor.hpp"
+
+#if REACTOR_LLVM_VERSION < 7
+#error "ENABLE_RR_DEBUG_INFO can currently only be used with LLVM 7+"
+#endif
+
+#include "backtrace.h"
+
+#include "llvm/Demangle/Demangle.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IRBuilder.h"
+
+#include <cctype>
+#include <fstream>
+#include <regex>
+#include <sstream>
+#include <string>
+
+#if 0
+#define LOG(msg, ...) printf(msg "\n", ##__VA_ARGS__)
+#else
+#define LOG(msg, ...)
+#endif
+
+namespace
+{
+	std::pair<llvm::StringRef, llvm::StringRef> splitPath(const char* path)
+	{
+		return llvm::StringRef(path).rsplit('/');
+	}
+} // anonymous namespaces
+
+namespace rr
+{
+	DebugInfo::DebugInfo(
+			llvm::IRBuilder<> *builder,
+			llvm::LLVMContext *context,
+			llvm::Module *module,
+			llvm::Function *function)
+		: builder(builder), context(context), module(module), function(function)
+	{
+		using namespace ::llvm;
+
+		auto location = getCallerLocation();
+
+		auto fileAndDir = splitPath(location.function.file.c_str());
+		diBuilder = new llvm::DIBuilder(*module);
+		diCU = diBuilder->createCompileUnit(
+			llvm::dwarf::DW_LANG_C,
+			diBuilder->createFile(fileAndDir.first, fileAndDir.second),
+			"Reactor",
+			0, "", 0);
+
+		jitEventListener = llvm::JITEventListener::createGDBRegistrationListener();
+		registerBasicTypes();
+
+		SmallVector<Metadata *, 8> EltTys;
+		auto funcTy = diBuilder->createSubroutineType(diBuilder->getOrCreateTypeArray(EltTys));
+
+		auto file = getOrCreateFile(location.function.file.c_str());
+		auto sp = diBuilder->createFunction(
+			file,                   // scope
+			"ReactorFunction",      // function name
+			"ReactorFunction",      // linkage
+			file,                   // file
+			location.line,          // line
+			funcTy,                 // type
+			false,                  // internal linkage
+			true,                   // definition
+			location.line,          // scope line
+			DINode::FlagPrototyped, // flags
+			false                   // is optimized
+		);
+		diSubprogram = sp;
+		function->setSubprogram(sp);
+		diRootLocation = DILocation::get(*context, location.line, 0, sp);
+		builder->SetCurrentDebugLocation(diRootLocation);
+	}
+
+	void DebugInfo::Finalize()
+	{
+		while (diScope.size() > 0)
+		{
+			emitPending(diScope.back(), builder, diBuilder);
+			diScope.pop_back();
+		}
+		diBuilder->finalize();
+	}
+
+	void DebugInfo::EmitLocation()
+	{
+		auto const& backtrace = getCallerBacktrace();
+		syncScope(backtrace);
+		builder->SetCurrentDebugLocation(getLocation(backtrace, backtrace.size() - 1));
+	}
+
+	void DebugInfo::Flush()
+	{
+		emitPending(diScope.back(), builder, diBuilder);
+	}
+
+	void DebugInfo::syncScope(Backtrace const& backtrace)
+	{
+		auto shrink = [this](size_t newsize)
+		{
+			while (diScope.size() > newsize)
+			{
+				auto &scope = diScope.back();
+				LOG("- STACK(%d): di: %p, location: %s:%d",
+					int(diScope.size() - 1), scope.di,
+					scope.location.function.file.c_str(),
+					int(scope.location.line));
+				emitPending(scope, builder, diBuilder);
+				diScope.pop_back();
+			}
+		};
+
+		if (backtrace.size() < diScope.size())
+		{
+			shrink(backtrace.size());
+		}
+
+		for (size_t i = 0; i < diScope.size(); i++)
+		{
+			auto &scope = diScope[i];
+			auto const &oldLocation = scope.location;
+			auto const &newLocation = backtrace[i];
+
+			if (oldLocation.function != newLocation.function)
+			{
+				LOG("  STACK(%d): Changed function %s -> %s", int(i),
+					oldLocation.function.name.c_str(), newLocation.function.name.c_str());
+				shrink(i);
+				break;
+			}
+
+			if (oldLocation.line > newLocation.line)
+			{
+				// Create a new di block to shadow all the variables in the loop.
+				auto file = getOrCreateFile(newLocation.function.file.c_str());
+				auto di = diBuilder->createLexicalBlock(scope.di, file, newLocation.line, 0);
+				LOG("  STACK(%d): Jumped backwards %d -> %d. di: %p -> %p", int(i),
+					oldLocation.line, newLocation.line, scope.di, di);
+				emitPending(scope, builder, diBuilder);
+				scope = {newLocation, di};
+				shrink(i+1);
+				break;
+			}
+
+			scope.location = newLocation;
+		}
+
+		while (backtrace.size() > diScope.size())
+		{
+			auto i = diScope.size();
+			auto location = backtrace[i];
+			auto file = getOrCreateFile(location.function.file.c_str());
+			auto funcTy = diBuilder->createSubroutineType(diBuilder->getOrCreateTypeArray({}));
+
+			char buf[1024];
+			size_t size = sizeof(buf);
+			int status = 0;
+			llvm::itaniumDemangle(location.function.name.c_str(), buf, &size, &status);
+			auto name = status == 0 ? buf : location.function.name.c_str();
+
+			auto func = diBuilder->createFunction(
+				file,                           // scope
+				name,                           // function name
+				"",                             // linkage
+				file,                           // file
+				location.line,                  // line
+				funcTy,                         // type
+				false,                          // internal linkage
+				true,                           // definition
+				location.line,                  // scope line
+				llvm::DINode::FlagPrototyped,   // flags
+				false                           // is optimized
+			);
+			diScope.push_back({location, func});
+			LOG("+ STACK(%d): di: %p, location: %s:%d", int(i), di,
+				location.function.file.c_str(), int(location.line));
+		}
+	}
+
+	llvm::DILocation* DebugInfo::getLocation(const Backtrace &backtrace, size_t i)
+	{
+		if (backtrace.size() == 0) { return nullptr; }
+		assert(backtrace.size() == diScope.size());
+		return llvm::DILocation::get(
+			*context,
+			backtrace[i].line,
+			0,
+			diScope[i].di,
+			i > 0 ? getLocation(backtrace, i - 1) : diRootLocation
+		);
+	}
+
+	void DebugInfo::EmitVariable(Value *variable)
+	{
+		auto const& backtrace = getCallerBacktrace();
+		syncScope(backtrace);
+
+		for (int i = backtrace.size() - 1; i >= 0; i--)
+		{
+			auto const &location = backtrace[i];
+			auto tokens = getOrParseFileTokens(location.function.file.c_str());
+			auto tokIt = tokens->find(location.line);
+			if (tokIt == tokens->end())
+			{
+				break;
+			}
+			auto token = tokIt->second;
+			auto name = token.identifier;
+			if (token.kind == Token::Return)
+			{
+				// This is a:
+				//
+				//   return <expr>;
+				//
+				// Emit this expression as two variables -
+				// Once as a synthetic 'return_value' variable at this scope.
+				// Again by bubbling the expression value up the callstack as
+				// Return Value Optimizations (RVOs) are likely to carry across
+				// the value to a local without calling a constructor in
+				// statements like:
+				//
+				//   auto val = foo();
+				//
+				name = "return_value";
+			}
+
+			auto &scope = diScope[i];
+			if (scope.pending.location != location)
+			{
+				emitPending(scope, builder, diBuilder);
+			}
+
+			auto value = V(variable);
+			auto block = builder->GetInsertBlock();
+
+			auto insertAfter = block->size() > 0 ? &block->back() : nullptr;
+			while (insertAfter != nullptr && insertAfter->isTerminator())
+			{
+				insertAfter = insertAfter->getPrevNode();
+			}
+
+			scope.pending = Pending{};
+			scope.pending.name = name;
+			scope.pending.location = location;
+			scope.pending.diLocation = getLocation(backtrace, i);
+			scope.pending.value = value;
+			scope.pending.block = block;
+			scope.pending.insertAfter = insertAfter;
+			scope.pending.scope = scope.di;
+
+			if (token.kind == Token::Return)
+			{
+				// Insert a noop instruction so the debugger can inspect the
+				// return value before the function scope closes.
+				scope.pending.addNopOnNextLine = true;
+			}
+			else
+			{
+				break;
+			}
+		}
+	}
+
+	void DebugInfo::emitPending(Scope &scope, IRBuilder *builder, llvm::DIBuilder *diBuilder)
+	{
+		auto const &pending = scope.pending;
+		if (pending.value == nullptr)
+		{
+			return;
+		}
+
+		if (!scope.symbols.emplace(pending.name).second)
+		{
+			return;
+		}
+
+		bool isAlloca = llvm::isa<llvm::AllocaInst>(pending.value);
+
+		LOG("  EMIT(%s): di: %p, location: %s:%d, isAlloca: %s", pending.name.c_str(), scope.di,
+			pending.location.function.file.c_str(), pending.location.line, isAlloca ? "true" : "false");
+
+		auto value = pending.value;
+
+		IRBuilder::InsertPointGuard guard(*builder);
+		if (pending.insertAfter != nullptr)
+		{
+			builder->SetInsertPoint(pending.block, ++pending.insertAfter->getIterator());
+		}
+		else
+		{
+			builder->SetInsertPoint(pending.block);
+		}
+		builder->SetCurrentDebugLocation(pending.diLocation);
+
+		if (!isAlloca)
+		{
+			// While insertDbgValueIntrinsic should be enough to declare a
+			// variable with no storage, variables of RValues can share the same
+			// llvm::Value, and only one can be named. Take for example:
+			//
+			//   Int a = 42;
+			//   RValue<Int> b = a;
+			//   RValue<Int> c = b;
+			//
+			// To handle this, always promote named RValues to an alloca.
+
+			llvm::BasicBlock &entryBlock = function->getEntryBlock();
+			auto alloca = new llvm::AllocaInst(value->getType(), 0, pending.name);
+			entryBlock.getInstList().push_front(alloca);
+			builder->CreateStore(value, alloca);
+			value = alloca;
+		}
+
+		value->setName(pending.name);
+
+		auto diFile = getOrCreateFile(pending.location.function.file.c_str());
+		auto diType = getOrCreateType(value->getType()->getPointerElementType());
+		auto diVar = diBuilder->createAutoVariable(scope.di, pending.name, diFile, pending.location.line, diType);
+
+		auto di = diBuilder->insertDeclare(value, diVar, diBuilder->createExpression(), pending.diLocation, pending.block);
+		if (pending.insertAfter != nullptr) { di->moveAfter(pending.insertAfter); }
+
+		if (pending.addNopOnNextLine)
+		{
+			builder->SetCurrentDebugLocation(llvm::DILocation::get(
+				*context,
+				pending.diLocation->getLine() + 1,
+				0,
+				pending.diLocation->getScope(),
+				pending.diLocation->getInlinedAt()
+			));
+			Nop();
+		}
+
+		scope.pending = Pending{};
+	}
+
+	void DebugInfo::NotifyObjectEmitted(const llvm::object::ObjectFile &Obj, const llvm::LoadedObjectInfo &L)
+	{
+		jitEventListener->NotifyObjectEmitted(Obj, static_cast<const llvm::RuntimeDyld::LoadedObjectInfo&>(L));
+	}
+
+	void DebugInfo::NotifyFreeingObject(const llvm::object::ObjectFile &Obj)
+	{
+		jitEventListener->NotifyFreeingObject(Obj);
+	}
+
+	void DebugInfo::registerBasicTypes()
+	{
+		using namespace rr;
+		using namespace llvm;
+
+		auto vec4 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 4));
+		auto vec8 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 8));
+		auto vec16 = diBuilder->getOrCreateArray(diBuilder->getOrCreateSubrange(0, 16));
+
+		diTypes.emplace(T(Bool::getType()), diBuilder->createBasicType("Bool", sizeof(bool), dwarf::DW_ATE_boolean));
+		diTypes.emplace(T(Byte::getType()), diBuilder->createBasicType("Byte", 8, dwarf::DW_ATE_unsigned_char));
+		diTypes.emplace(T(SByte::getType()), diBuilder->createBasicType("SByte", 8, dwarf::DW_ATE_signed_char));
+		diTypes.emplace(T(Short::getType()), diBuilder->createBasicType("Short", 16, dwarf::DW_ATE_signed));
+		diTypes.emplace(T(UShort::getType()), diBuilder->createBasicType("UShort", 16, dwarf::DW_ATE_unsigned));
+		diTypes.emplace(T(Int::getType()), diBuilder->createBasicType("Int", 32, dwarf::DW_ATE_signed));
+		diTypes.emplace(T(UInt::getType()), diBuilder->createBasicType("UInt", 32, dwarf::DW_ATE_unsigned));
+		diTypes.emplace(T(Long::getType()), diBuilder->createBasicType("Long", 64, dwarf::DW_ATE_signed));
+		diTypes.emplace(T(Half::getType()), diBuilder->createBasicType("Half", 16, dwarf::DW_ATE_float));
+		diTypes.emplace(T(Float::getType()), diBuilder->createBasicType("Float", 32, dwarf::DW_ATE_float));
+
+		diTypes.emplace(T(Byte4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::getType())], {vec16}));
+		diTypes.emplace(T(SByte4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::getType())], {vec16}));
+		diTypes.emplace(T(Byte8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::getType())], {vec16}));
+		diTypes.emplace(T(SByte8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::getType())], {vec16}));
+		diTypes.emplace(T(Byte16::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Byte::getType())], {vec16}));
+		diTypes.emplace(T(SByte16::getType()), diBuilder->createVectorType(128, 128, diTypes[T(SByte::getType())], {vec16}));
+		diTypes.emplace(T(Short2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Short::getType())], {vec8}));
+		diTypes.emplace(T(UShort2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::getType())], {vec8}));
+		diTypes.emplace(T(Short4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Short::getType())], {vec8}));
+		diTypes.emplace(T(UShort4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::getType())], {vec8}));
+		diTypes.emplace(T(Short8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Short::getType())], {vec8}));
+		diTypes.emplace(T(UShort8::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UShort::getType())], {vec8}));
+		diTypes.emplace(T(Int2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Int::getType())], {vec4}));
+		diTypes.emplace(T(UInt2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UInt::getType())], {vec4}));
+		diTypes.emplace(T(Int4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Int::getType())], {vec4}));
+		diTypes.emplace(T(UInt4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(UInt::getType())], {vec4}));
+		diTypes.emplace(T(Float2::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Float::getType())], {vec4}));
+		diTypes.emplace(T(Float4::getType()), diBuilder->createVectorType(128, 128, diTypes[T(Float::getType())], {vec4}));
+	}
+
+	DebugInfo::Location DebugInfo::getCallerLocation() const
+	{
+		return getCallerBacktrace(1)[0];
+	}
+
+	DebugInfo::Backtrace DebugInfo::getCallerBacktrace(size_t limit /* = 0 */) const
+	{
+		struct callbacks
+		{
+			static void onError(void *data, const char *msg, int errnum)
+			{
+				fprintf(stderr, "BACKTRACE ERROR %d: %s\n", errnum, msg);
+			}
+
+			static int onPCInfo(void *data, uintptr_t pc, const char *file, int line, const char *function)
+			{
+				if (file == nullptr) { return 0; }
+
+				auto const &fileSR = llvm::StringRef(file);
+				if (fileSR.endswith("ReactorDebugInfo.cpp") ||
+					fileSR.endswith("Reactor.cpp") ||
+					fileSR.endswith("Reactor.hpp"))
+				{
+					return 0;
+				}
+
+				auto cb = reinterpret_cast<callbacks*>(data);
+
+				Location location;
+				location.function.file = file;
+				location.function.name = function;
+				location.line = line;
+
+				cb->locations.push_back(location);
+				return (cb->limit == 0 || sizeof(cb->locations) < cb->limit) ? 0 : 1;
+			}
+
+			size_t limit;
+			std::vector<DebugInfo::Location> locations;
+		};
+
+		callbacks callbacks;
+		callbacks.limit = limit;
+		static auto state = backtrace_create_state(nullptr, 0, &callbacks::onError, nullptr);
+		backtrace_full(state, 1, &callbacks::onPCInfo, &callbacks::onError, &callbacks);
+
+		std::reverse(callbacks.locations.begin(), callbacks.locations.end());
+
+		return callbacks.locations;
+	}
+
+	llvm::DIType *DebugInfo::getOrCreateType(llvm::Type* type)
+	{
+		auto it = diTypes.find(type);
+		if (it != diTypes.end()) { return it->second; }
+
+		if(type->isPointerTy())
+		{
+			auto dbgTy = diBuilder->createPointerType(
+				getOrCreateType(type->getPointerElementType()),
+				sizeof(void*)*8, alignof(void*)*8);
+			diTypes.emplace(type, dbgTy);
+			return dbgTy;
+		}
+		llvm::errs() << "Unimplemented debug type: " << type << "\n";
+		assert(false);
+	}
+
+	llvm::DIFile *DebugInfo::getOrCreateFile(const char* path)
+	{
+		auto it = diFiles.find(path);
+		if (it != diFiles.end()) { return it->second; }
+		auto dirAndName = splitPath(path);
+		auto file = diBuilder->createFile(dirAndName.second, dirAndName.first);
+		diFiles.emplace(path, file);
+		return file;
+	}
+
+	DebugInfo::LineTokens const *DebugInfo::getOrParseFileTokens(const char* path)
+	{
+		static std::regex reLocalDecl(
+			"^" // line start
+			"\\s*" // initial whitespace
+			"(?:For\\s*\\(\\s*)?" // optional 'For ('
+			"((?:\\w+(?:<[^>]+>)?)(?:::\\w+(?:<[^>]+>)?)*)" // type (match group 1)
+			"\\s+" // whitespace between type and name
+			"(\\w+)" // identifier (match group 2)
+			"\\s*" // whitespace after identifier
+			"(\\[.*\\])?"); // optional array suffix (match group 3)
+
+		auto it = fileTokens.find(path);
+		if (it != fileTokens.end())
+		{
+			return it->second.get();
+		}
+
+		auto tokens = std::unique_ptr<LineTokens>(new LineTokens());
+
+		std::ifstream file(path);
+		std::string line;
+		int lineCount = 0;
+		while (std::getline(file, line))
+		{
+			lineCount++;
+			std::smatch match;
+			if (std::regex_search(line, match, reLocalDecl) && match.size() > 3)
+			{
+				bool isArray = match.str(3) != "";
+				if (!isArray) // Cannot deal with C-arrays of values.
+				{
+					if (match.str(1) == "return")
+					{
+						(*tokens)[lineCount] = Token{Token::Return};
+					}
+					else
+					{
+						(*tokens)[lineCount] = Token{Token::Identifier, match.str(2)};
+					}
+				}
+			}
+		}
+
+		auto out = tokens.get();
+		fileTokens.emplace(path, std::move(tokens));
+		return out;
+	}
+
+} // namespace rr
+
+#endif // ENABLE_RR_DEBUG_INFO
diff --git a/src/Reactor/LLVMReactorDebugInfo.hpp b/src/Reactor/LLVMReactorDebugInfo.hpp
new file mode 100644
index 0000000..d8c83de
--- /dev/null
+++ b/src/Reactor/LLVMReactorDebugInfo.hpp
@@ -0,0 +1,211 @@
+// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef rr_LLVMReactorDebugInfo_hpp
+#define rr_LLVMReactorDebugInfo_hpp
+
+#include "Reactor.hpp"
+
+#ifdef ENABLE_RR_DEBUG_INFO
+
+#include <unordered_set>
+#include <unordered_map>
+#include <vector>
+#include <memory>
+
+// Forward declarations
+namespace llvm
+{
+	class BasicBlock;
+	class ConstantFolder;
+	class DIBuilder;
+	class DICompileUnit;
+	class DIFile;
+	class DILocation;
+	class DIScope;
+	class DISubprogram;
+	class DIType;
+	class Function;
+	class Instruction;
+	class IRBuilderDefaultInserter;
+	class JITEventListener;
+	class LLVMContext;
+	class LoadedObjectInfo;
+	class Module;
+	class Type;
+	class Value;
+
+	namespace object
+	{
+		class ObjectFile;
+	}
+
+	template <typename T, typename Inserter> class IRBuilder;
+} // namespace llvm
+
+namespace rr
+{
+	class Type;
+	class Value;
+
+	// DebugInfo generates LLVM DebugInfo IR from the C++ source that calls
+	// into Reactor functions. See docs/ReactorDebugInfo.mk for more information.
+	class DebugInfo
+	{
+	public:
+		using IRBuilder = llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>;
+
+		DebugInfo(IRBuilder *builder,
+				llvm::LLVMContext *context,
+				llvm::Module *module,
+				llvm::Function *function);
+
+		// Finalize debug info generation. Must be called before the LLVM module
+		// is built.
+		void Finalize();
+
+		// Updates the current source location.
+		void EmitLocation();
+
+		// Binds the value to its symbol in the source file.
+		// See docs/ReactorDebugInfo.mk for more information.
+		void EmitVariable(Value *value);
+
+		// Forcefully flush the binding of the last variable name.
+		// Used for binding the initializer of `For` loops.
+		void Flush();
+
+		// NotifyObjectEmitted informs any attached debuggers of the JIT'd
+		// object.
+		void NotifyObjectEmitted(const llvm::object::ObjectFile &Obj, const llvm::LoadedObjectInfo &L);
+
+		// NotifyFreeingObject informs any attached debuggers that the JIT'd
+		// object is now invalid.
+		void NotifyFreeingObject(const llvm::object::ObjectFile &Obj);
+
+	private:
+		struct Token
+		{
+			enum Kind
+			{
+				Identifier,
+				Return
+			};
+			Kind kind;
+			std::string identifier;
+		};
+
+		using LineTokens = std::unordered_map<unsigned int, Token>;
+
+		struct FunctionLocation
+		{
+			std::string name;
+			std::string file;
+
+			bool operator == (const FunctionLocation &rhs) const { return name == rhs.name && file == rhs.file; }
+			bool operator != (const FunctionLocation &rhs) const { return !(*this == rhs); }
+
+			struct Hash
+			{
+				std::size_t operator()(const FunctionLocation &l) const noexcept
+				{
+					return std::hash<std::string>()(l.file) * 31 +
+							std::hash<std::string>()(l.name);
+				}
+			};
+		};
+
+		struct Location
+		{
+			FunctionLocation function;
+			unsigned int line = 0;
+
+			bool operator == (const Location &rhs) const { return function == rhs.function && line == rhs.line; }
+			bool operator != (const Location &rhs) const { return !(*this == rhs); }
+
+			struct Hash
+			{
+				std::size_t operator()(const Location &l) const noexcept
+				{
+					return FunctionLocation::Hash()(l.function) * 31 +
+							std::hash<unsigned int>()(l.line);
+				}
+			};
+		};
+
+		using Backtrace = std::vector<Location>;
+
+		struct Pending
+		{
+			std::string name;
+			Location location;
+			llvm::DILocation *diLocation = nullptr;
+			llvm::Value *value = nullptr;
+			llvm::Instruction *insertAfter = nullptr;
+			llvm::BasicBlock *block = nullptr;
+			llvm::DIScope *scope = nullptr;
+			bool addNopOnNextLine = false;
+		};
+
+		struct Scope
+		{
+			Location location;
+			llvm::DIScope *di;
+			std::unordered_set<std::string> symbols;
+			Pending pending;
+		};
+
+		void registerBasicTypes();
+
+		void emitPending(Scope &scope, IRBuilder *builder, llvm::DIBuilder *diBuilder);
+
+		// Returns the source location of the non-Reactor calling function.
+		Location getCallerLocation() const;
+
+		// Returns the backtrace for the callstack, starting at the first
+		// non-Reactor file. If limit is non-zero, then a maximum of limit
+		// frames will be returned.
+		Backtrace getCallerBacktrace(size_t limit = 0) const;
+
+		llvm::DILocation* getLocation(const Backtrace &backtrace, size_t i);
+
+		llvm::DIType *getOrCreateType(llvm::Type* type);
+		llvm::DIFile *getOrCreateFile(const char* path);
+		LineTokens const *getOrParseFileTokens(const char* path);
+
+		// Synchronizes diScope with the current backtrace.
+		void syncScope(Backtrace const& backtrace);
+
+		IRBuilder *builder;
+		llvm::LLVMContext *context;
+		llvm::Module *module;
+		llvm::Function *function;
+
+		llvm::DIBuilder *diBuilder;
+		llvm::DICompileUnit *diCU;
+		llvm::DISubprogram *diSubprogram;
+		llvm::DILocation *diRootLocation;
+		std::vector<Scope> diScope;
+		std::unordered_map<std::string, llvm::DIFile*> diFiles;
+		std::unordered_map<llvm::Type*, llvm::DIType*> diTypes;
+		std::unordered_map<std::string, std::unique_ptr<LineTokens>> fileTokens;
+		llvm::JITEventListener *jitEventListener;
+		std::vector<void const*> pushed;
+	};
+
+} // namespace rr
+
+#endif // ENABLE_RR_DEBUG_INFO
+
+#endif // rr_LLVMReactorDebugInfo_hpp
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index b7dcaf3..4e95806 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -32,6 +32,27 @@
 #define ENABLE_RR_PRINT 1 // Enables RR_PRINT(), RR_WATCH()
 #endif // !defined(NDEBUG) && (REACTOR_LLVM_VERSION >= 7)
 
+#ifdef ENABLE_RR_DEBUG_INFO
+	// Functions used for generating JIT debug info.
+	// See docs/ReactorDebugInfo.md for more information.
+	namespace rr
+	{
+		// Update the current source location for debug.
+		void EmitDebugLocation();
+		// Bind value to its symbolic name taken from the backtrace.
+		void EmitDebugVariable(class Value* value);
+		// Flush any pending variable bindings before the line ends.
+		void FlushDebug();
+	}
+	#define RR_DEBUG_INFO_UPDATE_LOC()    rr::EmitDebugLocation()
+	#define RR_DEBUG_INFO_EMIT_VAR(value) rr::EmitDebugVariable(value)
+	#define RR_DEBUG_INFO_FLUSH()         rr::FlushDebug()
+#else
+	#define RR_DEBUG_INFO_UPDATE_LOC()
+	#define RR_DEBUG_INFO_EMIT_VAR(value)
+	#define RR_DEBUG_INFO_FLUSH()
+#endif // ENABLE_RR_DEBUG_INFO
+
 namespace rr
 {
 	struct Capabilities
@@ -211,6 +232,10 @@
 	public:
 		explicit RValue(Value *rvalue);
 
+#ifdef ENABLE_RR_DEBUG_INFO
+		RValue(const RValue<T> &rvalue);
+#endif // ENABLE_RR_DEBUG_INFO
+
 		RValue(const T &lvalue);
 		RValue(typename BoolLiteral<T>::type i);
 		RValue(typename IntLiteral<T>::type i);
@@ -2385,6 +2410,9 @@
 	template<class T>
 	LValue<T>::LValue(int arraySize) : Variable(T::getType(), arraySize)
 	{
+#ifdef ENABLE_RR_DEBUG_INFO
+		materialize();
+#endif // ENABLE_RR_DEBUG_INFO
 	}
 
 	inline void Variable::materialize() const
@@ -2392,6 +2420,7 @@
 		if(!address)
 		{
 			address = Nucleus::allocateStackVariable(type, arraySize);
+			RR_DEBUG_INFO_EMIT_VAR(address);
 
 			if(rvalue)
 			{
@@ -2488,47 +2517,62 @@
 		return alignment;
 	}
 
+#ifdef ENABLE_RR_DEBUG_INFO
+	template<class T>
+	RValue<T>::RValue(const RValue<T> &rvalue) : value(rvalue.value)
+	{
+		RR_DEBUG_INFO_EMIT_VAR(value);
+	}
+#endif // ENABLE_RR_DEBUG_INFO
+
 	template<class T>
 	RValue<T>::RValue(Value *rvalue)
 	{
 		assert(Nucleus::createBitCast(rvalue, T::getType()) == rvalue);   // Run-time type should match T, so bitcast is no-op.
 
 		value = rvalue;
+		RR_DEBUG_INFO_EMIT_VAR(value);
 	}
 
 	template<class T>
 	RValue<T>::RValue(const T &lvalue)
 	{
 		value = lvalue.loadValue();
+		RR_DEBUG_INFO_EMIT_VAR(value);
 	}
 
 	template<class T>
 	RValue<T>::RValue(typename BoolLiteral<T>::type i)
 	{
 		value = Nucleus::createConstantBool(i);
+		RR_DEBUG_INFO_EMIT_VAR(value);
 	}
 
 	template<class T>
 	RValue<T>::RValue(typename IntLiteral<T>::type i)
 	{
 		value = Nucleus::createConstantInt(i);
+		RR_DEBUG_INFO_EMIT_VAR(value);
 	}
 
 	template<class T>
 	RValue<T>::RValue(typename FloatLiteral<T>::type f)
 	{
 		value = Nucleus::createConstantFloat(f);
+		RR_DEBUG_INFO_EMIT_VAR(value);
 	}
 
 	template<class T>
 	RValue<T>::RValue(const Reference<T> &ref)
 	{
 		value = ref.loadValue();
+		RR_DEBUG_INFO_EMIT_VAR(value);
 	}
 
 	template<class Vector4, int T>
 	Swizzle2<Vector4, T>::operator RValue<Vector4>() const
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *vector = parent->loadValue();
 
 		return Swizzle(RValue<Vector4>(vector), T);
@@ -2537,6 +2581,7 @@
 	template<class Vector4, int T>
 	Swizzle4<Vector4, T>::operator RValue<Vector4>() const
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *vector = parent->loadValue();
 
 		return Swizzle(RValue<Vector4>(vector), T);
@@ -2545,6 +2590,7 @@
 	template<class Vector4, int T>
 	SwizzleMask4<Vector4, T>::operator RValue<Vector4>() const
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *vector = parent->loadValue();
 
 		return Swizzle(RValue<Vector4>(vector), T);
@@ -2553,24 +2599,28 @@
 	template<class Vector4, int T>
 	RValue<Vector4> SwizzleMask4<Vector4, T>::operator=(RValue<Vector4> rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return Mask(*parent, rhs, T);
 	}
 
 	template<class Vector4, int T>
 	RValue<Vector4> SwizzleMask4<Vector4, T>::operator=(RValue<typename Scalar<Vector4>::Type> rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return Mask(*parent, Vector4(rhs), T);
 	}
 
 	template<class Vector4, int T>
 	SwizzleMask1<Vector4, T>::operator RValue<typename Scalar<Vector4>::Type>() const   // FIXME: Call a non-template function
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return Extract(*parent, T & 0x3);
 	}
 
 	template<class Vector4, int T>
 	SwizzleMask1<Vector4, T>::operator RValue<Vector4>() const
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *vector = parent->loadValue();
 
 		return Swizzle(RValue<Vector4>(vector), T);
@@ -2579,24 +2629,28 @@
 	template<class Vector4, int T>
 	RValue<Vector4> SwizzleMask1<Vector4, T>::operator=(float x)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return *parent = Insert(*parent, Float(x), T & 0x3);
 	}
 
 	template<class Vector4, int T>
 	RValue<Vector4> SwizzleMask1<Vector4, T>::operator=(RValue<Vector4> rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return Mask(*parent, Float4(rhs), T);
 	}
 
 	template<class Vector4, int T>
 	RValue<Vector4> SwizzleMask1<Vector4, T>::operator=(RValue<typename Scalar<Vector4>::Type> rhs)   // FIXME: Call a non-template function
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return *parent = Insert(*parent, rhs, T & 0x3);
 	}
 
 	template<class Vector4, int T>
 	SwizzleMask2<Vector4, T>::operator RValue<Vector4>() const
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *vector = parent->loadValue();
 
 		return Swizzle(RValue<Float4>(vector), T);
@@ -2605,6 +2659,7 @@
 	template<class Vector4, int T>
 	RValue<Vector4> SwizzleMask2<Vector4, T>::operator=(RValue<Vector4> rhs)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return Mask(*parent, Float4(rhs), T);
 	}
 
@@ -2635,24 +2690,28 @@
 	template<int X, int Y>
 	Float4::Float4(const Swizzle2<Float4, X> &x, const Swizzle2<Float4, Y> &y) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		*this = ShuffleLowHigh(*x.parent, *y.parent, (X & 0xF) | (Y & 0xF) << 4);
 	}
 
 	template<int X, int Y>
 	Float4::Float4(const SwizzleMask2<Float4, X> &x, const Swizzle2<Float4, Y> &y) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		*this = ShuffleLowHigh(*x.parent, *y.parent, (X & 0xF) | (Y & 0xF) << 4);
 	}
 
 	template<int X, int Y>
 	Float4::Float4(const Swizzle2<Float4, X> &x, const SwizzleMask2<Float4, Y> &y) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		*this = ShuffleLowHigh(*x.parent, *y.parent, (X & 0xF) | (Y & 0xF) << 4);
 	}
 
 	template<int X, int Y>
 	Float4::Float4(const SwizzleMask2<Float4, X> &x, const SwizzleMask2<Float4, Y> &y) : XYZW(this)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		*this = ShuffleLowHigh(*x.parent, *y.parent, (X & 0xF) | (Y & 0xF) << 4);
 	}
 
@@ -2736,6 +2795,7 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator[](int index)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), Nucleus::createConstantInt(index), false);
 
 		return Reference<T>(element, alignment);
@@ -2744,6 +2804,7 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator[](unsigned int index)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), Nucleus::createConstantInt(index), true);
 
 		return Reference<T>(element, alignment);
@@ -2752,6 +2813,7 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator[](RValue<Int> index)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), index.value, false);
 
 		return Reference<T>(element, alignment);
@@ -2760,6 +2822,7 @@
 	template<class T>
 	Reference<T> Pointer<T>::operator[](RValue<UInt> index)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *element = Nucleus::createGEP(LValue<Pointer<T>>::loadValue(), T::getType(), index.value, true);
 
 		return Reference<T>(element, alignment);
@@ -2835,12 +2898,14 @@
 	template<class T>
 	RValue<T> IfThenElse(RValue<Bool> condition, RValue<T> ifTrue, RValue<T> ifFalse)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<T>(Nucleus::createSelect(condition.value, ifTrue.value, ifFalse.value));
 	}
 
 	template<class T>
 	RValue<T> IfThenElse(RValue<Bool> condition, const T &ifTrue, RValue<T> ifFalse)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *trueValue = ifTrue.loadValue();
 
 		return RValue<T>(Nucleus::createSelect(condition.value, trueValue, ifFalse.value));
@@ -2849,6 +2914,7 @@
 	template<class T>
 	RValue<T> IfThenElse(RValue<Bool> condition, RValue<T> ifTrue, const T &ifFalse)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *falseValue = ifFalse.loadValue();
 
 		return RValue<T>(Nucleus::createSelect(condition.value, ifTrue.value, falseValue));
@@ -2857,6 +2923,7 @@
 	template<class T>
 	RValue<T> IfThenElse(RValue<Bool> condition, const T &ifTrue, const T &ifFalse)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *trueValue = ifTrue.loadValue();
 		Value *falseValue = ifFalse.loadValue();
 
@@ -2866,6 +2933,7 @@
 	template<class T>
 	void Return(const Pointer<T> &ret)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Nucleus::createRet(Nucleus::createLoad(ret.address, Pointer<T>::getType()));
 		Nucleus::setInsertBlock(Nucleus::createBasicBlock());
 		Nucleus::createUnreachable();
@@ -2874,6 +2942,7 @@
 	template<class T>
 	void Return(RValue<Pointer<T>> ret)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Nucleus::createRet(ret.value);
 		Nucleus::setInsertBlock(Nucleus::createBasicBlock());
 		Nucleus::createUnreachable();
@@ -2918,12 +2987,14 @@
 	template<class T, class S>
 	RValue<T> ReinterpretCast(RValue<S> val)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<T>(Nucleus::createBitCast(val.value, T::getType()));
 	}
 
 	template<class T, class S>
 	RValue<T> ReinterpretCast(const LValue<S> &var)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		Value *val = var.loadValue();
 
 		return RValue<T>(Nucleus::createBitCast(val, T::getType()));
@@ -2938,6 +3009,7 @@
 	template<class T>
 	RValue<T> As(Value *val)
 	{
+		RR_DEBUG_INFO_UPDATE_LOC();
 		return RValue<T>(Nucleus::createBitCast(val, T::getType()));
 	}
 
@@ -3050,6 +3122,10 @@
 		CallHelper<FUNCTION_SIGNATURE>::Call(fptr, args...);
 	}
 
+	// Breakpoint emits an instruction that will cause the application to trap.
+	// This can be used to stop an attached debugger at the given call.
+	void Breakpoint();
+
 #ifdef ENABLE_RR_PRINT
 	// PrintValue holds the printf format and value(s) for a single argument
 	// to Print(). A single argument can be expanded into multiple printf
@@ -3387,6 +3463,7 @@
 
 		bool setup()
 		{
+			RR_DEBUG_INFO_FLUSH();
 			if(Nucleus::getInsertBlock() != endBB)
 			{
 				testBB = Nucleus::createBasicBlock();
diff --git a/src/Reactor/Reactor.vcxproj b/src/Reactor/Reactor.vcxproj
index ee0825e..ab5b1ec 100644
--- a/src/Reactor/Reactor.vcxproj
+++ b/src/Reactor/Reactor.vcxproj
@@ -289,6 +289,7 @@
     <ClCompile Include="LLVMRoutine.cpp" />

     <ClCompile Include="LLVMRoutineManager.cpp" />

     <ClCompile Include="LLVMReactor.cpp" />

+    <ClCompile Include="LLVMReactorDebugInfo.cpp" />

     <ClCompile Include="ExecutableMemory.cpp" />

     <ClCompile Include="Reactor.cpp" />

     <ClCompile Include="Routine.cpp" />

@@ -297,6 +298,8 @@
   <ItemGroup>

     <ClInclude Include="CPUID.hpp" />

     <ClInclude Include="Debug.hpp" />

+    <ClInclude Include="LLVMReactor.hpp" />

+    <ClInclude Include="LLVMReactorDebugInfo.hpp" />

     <ClInclude Include="LLVMRoutine.hpp" />

     <ClInclude Include="LLVMRoutineManager.hpp" />

     <ClInclude Include="ExecutableMemory.hpp" />

diff --git a/src/Reactor/Reactor.vcxproj.filters b/src/Reactor/Reactor.vcxproj.filters
index 30d695f..c8a2c50 100644
--- a/src/Reactor/Reactor.vcxproj.filters
+++ b/src/Reactor/Reactor.vcxproj.filters
@@ -27,6 +27,9 @@
     <ClCompile Include="LLVMReactor.cpp">

       <Filter>Source Files</Filter>

     </ClCompile>

+    <ClCompile Include="LLVMReactorDebugInfo.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

     <ClCompile Include="CPUID.cpp">

       <Filter>Source Files</Filter>

     </ClCompile>

@@ -56,6 +59,12 @@
     <ClInclude Include="Routine.hpp">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="LLVMReactor.hpp">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="LLVMReactorDebugInfo.hpp">

+      <Filter>Header Files</Filter>

+    </ClInclude>

     <ClInclude Include="LLVMRoutineManager.hpp">

       <Filter>Header Files</Filter>

     </ClInclude>

diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 731e682..3afed7b 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -3425,4 +3425,8 @@
 	RValue<Float4> Log2(RValue<Float4> x) { UNIMPLEMENTED("Subzero Log2()"); return Float4(0); }
 	RValue<UInt4> Ctlz(RValue<UInt4> x, bool isZeroUndef) { UNIMPLEMENTED("Subzero Ctlz()"); return UInt4(0); }
 	RValue<UInt4> Cttz(RValue<UInt4> x, bool isZeroUndef) { UNIMPLEMENTED("Subzero Cttz()"); return UInt4(0); }
+
+	void EmitDebugLocation() {}
+	void EmitDebugVariable(Value* value) {}
+	void FlushDebug() {}
 }
diff --git a/third_party/libbacktrace/config/darwin/include/backtrace-supported.h b/third_party/libbacktrace/config/darwin/include/backtrace-supported.h
new file mode 100644
index 0000000..7709fca
--- /dev/null
+++ b/third_party/libbacktrace/config/darwin/include/backtrace-supported.h
@@ -0,0 +1,66 @@
+/* backtrace-supported.h.in -- Whether stack backtrace is supported.
+   Copyright (C) 2012-2016 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* The file backtrace-supported.h.in is used by configure to generate
+   the file backtrace-supported.h.  The file backtrace-supported.h may
+   be #include'd to see whether the backtrace library will be able to
+   get a backtrace and produce symbolic information.  */
+
+
+/* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library
+   should work, 0 if it will not.  Libraries may #include this to make
+   other arrangements.  */
+
+#define BACKTRACE_SUPPORTED 1
+
+/* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace
+   library will call malloc as it works, 0 if it will call mmap
+   instead.  This may be used to determine whether it is safe to call
+   the backtrace functions from a signal handler.  In general this
+   only applies to calls like backtrace and backtrace_pcinfo.  It does
+   not apply to backtrace_simple, which never calls malloc.  It does
+   not apply to backtrace_print, which always calls fprintf and
+   therefore malloc.  */
+
+#define BACKTRACE_USES_MALLOC 0
+
+/* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace
+   library is configured with threading support, 0 if not.  If this is
+   0, the threaded parameter to backtrace_create_state must be passed
+   as 0.  */
+
+#define BACKTRACE_SUPPORTS_THREADS 1
+
+/* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo
+   will work for variables.  It will always work for functions.  */
+
+#define BACKTRACE_SUPPORTS_DATA 1
diff --git a/third_party/libbacktrace/config/darwin/include/config.h b/third_party/libbacktrace/config/darwin/include/config.h
new file mode 100644
index 0000000..ee92775
--- /dev/null
+++ b/third_party/libbacktrace/config/darwin/include/config.h
@@ -0,0 +1,150 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* ELF size: 32 or 64 */
+#define BACKTRACE_ELF_SIZE 64
+
+/* XCOFF size: 32 or 64 */
+#define BACKTRACE_XCOFF_SIZE unused
+
+/* Define to 1 if you have the __atomic functions */
+#define HAVE_ATOMIC_FUNCTIONS 1
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+   don't. */
+#define HAVE_DECL_STRNLEN 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define if dl_iterate_phdr is available. */
+/* #undef HAVE_DL_ITERATE_PHDR */
+
+/* Define to 1 if you have the fcntl function */
+#define HAVE_FCNTL 1
+
+/* Define if getexecname is available. */
+/* #undef HAVE_GETEXECNAME */
+
+/* Define if _Unwind_GetIPInfo is available. */
+#define HAVE_GETIPINFO 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `z' library (-lz). */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the <link.h> header file. */
+/* #undef HAVE_LINK_H */
+
+/* Define if AIX loadquery is available. */
+/* #undef HAVE_LOADQUERY */
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the __sync functions */
+#define HAVE_SYNC_FUNCTIONS 1
+
+/* Define to 1 if you have the <sys/ldr.h> header file. */
+/* #undef HAVE_SYS_LDR_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if -lz is available. */
+#define HAVE_ZLIB 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "package-unused"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "package-unused version-unused"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libbacktrace"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "version-unused"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
diff --git a/third_party/libbacktrace/config/linux/include/backtrace-supported.h b/third_party/libbacktrace/config/linux/include/backtrace-supported.h
new file mode 100644
index 0000000..7709fca
--- /dev/null
+++ b/third_party/libbacktrace/config/linux/include/backtrace-supported.h
@@ -0,0 +1,66 @@
+/* backtrace-supported.h.in -- Whether stack backtrace is supported.
+   Copyright (C) 2012-2016 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* The file backtrace-supported.h.in is used by configure to generate
+   the file backtrace-supported.h.  The file backtrace-supported.h may
+   be #include'd to see whether the backtrace library will be able to
+   get a backtrace and produce symbolic information.  */
+
+
+/* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library
+   should work, 0 if it will not.  Libraries may #include this to make
+   other arrangements.  */
+
+#define BACKTRACE_SUPPORTED 1
+
+/* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace
+   library will call malloc as it works, 0 if it will call mmap
+   instead.  This may be used to determine whether it is safe to call
+   the backtrace functions from a signal handler.  In general this
+   only applies to calls like backtrace and backtrace_pcinfo.  It does
+   not apply to backtrace_simple, which never calls malloc.  It does
+   not apply to backtrace_print, which always calls fprintf and
+   therefore malloc.  */
+
+#define BACKTRACE_USES_MALLOC 0
+
+/* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace
+   library is configured with threading support, 0 if not.  If this is
+   0, the threaded parameter to backtrace_create_state must be passed
+   as 0.  */
+
+#define BACKTRACE_SUPPORTS_THREADS 1
+
+/* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo
+   will work for variables.  It will always work for functions.  */
+
+#define BACKTRACE_SUPPORTS_DATA 1
diff --git a/third_party/libbacktrace/config/linux/include/config.h b/third_party/libbacktrace/config/linux/include/config.h
new file mode 100644
index 0000000..7333eca
--- /dev/null
+++ b/third_party/libbacktrace/config/linux/include/config.h
@@ -0,0 +1,150 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* ELF size: 32 or 64 */
+#define BACKTRACE_ELF_SIZE 64
+
+/* XCOFF size: 32 or 64 */
+#define BACKTRACE_XCOFF_SIZE unused
+
+/* Define to 1 if you have the __atomic functions */
+#define HAVE_ATOMIC_FUNCTIONS 1
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+   don't. */
+#define HAVE_DECL_STRNLEN 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define if dl_iterate_phdr is available. */
+#define HAVE_DL_ITERATE_PHDR 1
+
+/* Define to 1 if you have the fcntl function */
+#define HAVE_FCNTL 1
+
+/* Define if getexecname is available. */
+/* #undef HAVE_GETEXECNAME */
+
+/* Define if _Unwind_GetIPInfo is available. */
+#define HAVE_GETIPINFO 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `z' library (-lz). */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the <link.h> header file. */
+#define HAVE_LINK_H 1
+
+/* Define if AIX loadquery is available. */
+/* #undef HAVE_LOADQUERY */
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the __sync functions */
+#define HAVE_SYNC_FUNCTIONS 1
+
+/* Define to 1 if you have the <sys/ldr.h> header file. */
+/* #undef HAVE_SYS_LDR_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if -lz is available. */
+#define HAVE_ZLIB 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "package-unused"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "package-unused version-unused"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libbacktrace"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "version-unused"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */