From 09c4569c87f813773f00d30ad3ce4df94416e56f Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Thu, 17 Jan 2019 18:07:27 +0100
Subject: [PATCH] Implement line debuginfo

---
 Cargo.lock                       |  42 +++
 Cargo.toml                       |   7 +-
 abc.cpp                          |  35 ++
 example/mini_core_hello_world.rs |  11 +
 mini_core_hello_world            | Bin 0 -> 25736 bytes
 src/base.rs                      |  20 +-
 src/common.rs                    |   8 +
 src/debuginfo.rs                 | 529 +++++++++++++++++++++++++++++++
 src/lib.rs                       |  50 ++-
 test.sh                          |   8 +-
 10 files changed, 691 insertions(+), 19 deletions(-)
 create mode 100644 abc.cpp
 create mode 100755 mini_core_hello_world
 create mode 100644 src/debuginfo.rs

diff --git a/Cargo.lock b/Cargo.lock
index eef23132621..c4f89330377 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -22,6 +22,14 @@ dependencies = [
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "arrayvec"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "atty"
 version = "0.2.11"
@@ -284,6 +292,11 @@ dependencies = [
  "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "fallible-iterator"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "fuchsia-zircon"
 version = "0.3.3"
@@ -303,6 +316,18 @@ name = "gcc"
 version = "0.3.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "gimli"
+version = "0.16.1"
+source = "git+https://github.com/bjorn3/gimli.git?branch=impl_range_write#ff96c190bbb7a41623f009c969cb7ecd7a2716f4"
+dependencies = [
+ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "goblin"
 version = "0.0.19"
@@ -375,6 +400,11 @@ dependencies = [
  "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "nodrop"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "plain"
 version = "0.2.3"
@@ -565,6 +595,8 @@ dependencies = [
  "cranelift-module 0.26.0 (git+https://github.com/CraneStation/cranelift.git)",
  "cranelift-simplejit 0.26.0 (git+https://github.com/CraneStation/cranelift.git)",
  "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "faerie 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gimli 0.16.1 (git+https://github.com/bjorn3/gimli.git?branch=impl_range_write)",
  "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -630,6 +662,11 @@ dependencies = [
  "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "string-interner"
 version = "0.6.3"
@@ -816,6 +853,7 @@ dependencies = [
 "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum ar 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "579681b3fecd1e9d6b5ce6969e05f9feb913f296eddaf595be1166a5ca597bc4"
+"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
 "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
@@ -843,9 +881,11 @@ dependencies = [
 "checksum faerie 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "142ee8f6d2864117a92855815e710b03087763df41ab3c6a97ca25e00e178b98"
 "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
 "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
+"checksum fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eb7217124812dc5672b7476d0c2d20cfe9f7c0f1ba0904b674a9762a0212f72e"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
+"checksum gimli 0.16.1 (git+https://github.com/bjorn3/gimli.git?branch=impl_range_write)" = "<none>"
 "checksum goblin 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c65cd533b33e3d04c6e393225fa8919ddfcf5862ca8919c7f9a167c312ef41c2"
 "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
 "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
@@ -856,6 +896,7 @@ dependencies = [
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
 "checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1"
 "checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9"
+"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
 "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
 "checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
 "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
@@ -885,6 +926,7 @@ dependencies = [
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7"
 "checksum serde_json 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "574378d957d6dcdf1bbb5d562a15cbd5e644159432f84634b94e485267abbcc7"
+"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
 "checksum string-interner 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "abb38a0d8fe673c40b10b6b75abcb076a958cc10fb894f14993d9737c4c87000"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3"
diff --git a/Cargo.toml b/Cargo.toml
index be43b837608..30824626feb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,10 +23,12 @@ target-lexicon = "0.2.0"
 #goblin = "0.0.17"
 ar = "0.6.1"
 bitflags = "1.0.3"
-byteorder = "1.2.6"
+byteorder = "1.2.7"
 libc = "0.2.45"
 tempfile = "3.0.4"
 env_logger = "0.6"
+gimli = { git = "https://github.com/gimli-rs/gimli.git" }
+faerie = "0.7.1"
 
 # Uncomment to use local checkout of cranelift
 #[patch."https://github.com/CraneStation/cranelift.git"]
@@ -35,5 +37,8 @@ env_logger = "0.6"
 #cranelift-simplejit = { path = "../cranelift/lib/simplejit" }
 #cranelift-faerie = { path = "../cranelift/lib/faerie" }
 
+[patch."https://github.com/gimli-rs/gimli.git"]
+gimli = { git = "https://github.com/bjorn3/gimli.git", branch = "impl_range_write" }
+
 [profile.dev.overrides."*"]
 opt-level = 3
diff --git a/abc.cpp b/abc.cpp
new file mode 100644
index 00000000000..7f131fdd8fd
--- /dev/null
+++ b/abc.cpp
@@ -0,0 +1,35 @@
+// compile using g++ -std=c++11 -g -c abc.cpp -o abc.o
+
+struct Opaque;
+
+struct MyType {
+    unsigned int field_a;
+    int field_b;
+    void* field_c;
+    float field_d;
+    //double field_e;
+    //long long field_f;
+    bool field_g;
+    char field_h;
+    Opaque* field_i;
+};
+
+MyType bcd(int x, MyType a) {
+    MyType b = a;
+    MyType c = b;
+    MyType d = c;
+    MyType e = d;
+    MyType f = e;
+    MyType g = f;
+    MyType h = g;
+    MyType i = h;
+    MyType j = i;
+    MyType k = j;
+    MyType l = k;
+    MyType m = l;
+    return b;
+}
+int main() {
+    bcd(42, {});
+    return 0;
+}
diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs
index c4140ceaf1e..638db7d24ef 100644
--- a/example/mini_core_hello_world.rs
+++ b/example/mini_core_hello_world.rs
@@ -115,7 +115,18 @@ struct Unique<T: ?Sized> {
 
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
 
+fn take_f32(f: f32) {}
+fn take_unique(u: Unique<()>) {}
+
 fn main() {
+    take_unique(Unique {
+        pointer: 0 as *const (),
+        _marker: PhantomData,
+    });
+    take_f32(0.1);
+
+    //return;
+
     unsafe {
         let hello: &[u8] = b"Hello\0" as &[u8; 6];
         let ptr: *const u8 = hello as *const [u8] as *const u8;
diff --git a/mini_core_hello_world b/mini_core_hello_world
new file mode 100755
index 0000000000000000000000000000000000000000..f7f7af4b14465a76582bda46c9483476c13a1032
GIT binary patch
literal 25736
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
T)Zto;|4lV;KVzw|B`N+d>q|}!

literal 0
HcmV?d00001

diff --git a/src/base.rs b/src/base.rs
index f780a86515a..698a31312fc 100644
--- a/src/base.rs
+++ b/src/base.rs
@@ -69,6 +69,13 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
     let func_id = cx.module
         .declare_function(&name, linkage, &sig)
         .unwrap();
+    let mut debug_context = cx.debug_context.as_mut().map(|debug_context| FunctionDebugContext::new(
+        tcx,
+        debug_context,
+        mir,
+        &name,
+        &sig,
+    ));
 
     // Step 3. Make FunctionBuilder
     let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
@@ -101,6 +108,7 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
         clif_comments,
         constants: &mut cx.ccx,
         caches: &mut cx.caches,
+        spans: Vec::new(),
     };
 
     // Step 6. Codegen function
@@ -108,6 +116,7 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
         crate::abi::codegen_fn_prelude(&mut fx, start_ebb);
         codegen_fn_content(&mut fx);
     });
+    let spans = fx.spans.clone();
 
     // Step 7. Write function to file for debugging
     #[cfg(debug_assertions)]
@@ -119,8 +128,12 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
     // Step 9. Define function
     cx.caches.context.func = func;
     cx.module
-        .define_function(func_id, &mut cx.caches.context)
+        .define_function_peek_compiled(func_id, &mut cx.caches.context, |size, context, isa| {
+            debug_context.as_mut().map(|x| x.define(tcx, size, context, isa, &spans[..]));
+        })
         .unwrap();
+    //let module = &mut cx.module;
+    //let caches = &cx.caches;
     cx.caches.context.clear();
 }
 
@@ -154,6 +167,7 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
 
         fx.bcx.ins().nop();
         for stmt in &bb_data.statements {
+            fx.set_debug_loc(stmt.source_info);
             trans_stmt(fx, ebb, stmt);
         }
 
@@ -169,6 +183,8 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
             fx.add_comment(inst, terminator_head);
         }
 
+        fx.set_debug_loc(bb_data.terminator().source_info);
+
         match &bb_data.terminator().kind {
             TerminatorKind::Goto { target } => {
                 let ebb = fx.get_ebb(*target);
@@ -322,6 +338,8 @@ fn trans_stmt<'a, 'tcx: 'a>(
 ) {
     let _print_guard = PrintOnPanic(|| format!("stmt {:?}", stmt));
 
+    fx.set_debug_loc(stmt.source_info);
+
     #[cfg(debug_assertions)]
     match &stmt.kind {
         StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful
diff --git a/src/common.rs b/src/common.rs
index d5e07be302c..ded45af6d5e 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -539,6 +539,7 @@ pub struct FunctionCx<'a, 'tcx: 'a, B: Backend> {
     pub clif_comments: crate::pretty_clif::CommentWriter,
     pub constants: &'a mut crate::constant::ConstantCx,
     pub caches: &'a mut Caches<'tcx>,
+    pub spans: Vec<Span>,
 }
 
 impl<'a, 'tcx: 'a, B: Backend + 'a> fmt::Debug for FunctionCx<'a, 'tcx, B> {
@@ -617,4 +618,11 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
     pub fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
         *self.local_map.get(&local).unwrap()
     }
+
+    pub fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
+        // FIXME: record scope too
+        let index = self.spans.len() as u32;
+        self.spans.push(source_info.span);
+        self.bcx.set_srcloc(SourceLoc::new(index));
+    }
 }
diff --git a/src/debuginfo.rs b/src/debuginfo.rs
new file mode 100644
index 00000000000..f4744f6b7be
--- /dev/null
+++ b/src/debuginfo.rs
@@ -0,0 +1,529 @@
+extern crate gimli;
+
+use crate::prelude::*;
+
+use std::marker::PhantomData;
+
+use gimli::write::{
+    Address, AttributeValue, CompilationUnit, DebugAbbrev, DebugInfo, DebugLine, DebugRanges,
+    DebugRngLists, DebugStr, EndianVec, LineProgram, LineProgramId, LineProgramTable, Range,
+    RangeList, RangesTable, Result, SectionId, StringTable, UnitEntryId, UnitId, UnitTable, Writer,
+};
+use gimli::Format;
+
+// FIXME: use target endian
+use byteorder::ByteOrder;
+use gimli::RunTimeEndian;
+
+use faerie::*;
+
+fn target_endian(tcx: TyCtxt) -> RunTimeEndian {
+    use rustc::ty::layout::Endian;
+
+    match tcx.data_layout.endian {
+        Endian::Big => RunTimeEndian::Big,
+        Endian::Little => RunTimeEndian::Little,
+    }
+}
+struct DebugReloc {
+    offset: u32,
+    size: u8,
+    name: String,
+    addend: i64,
+}
+
+pub struct DebugContext<'tcx> {
+    endian: RunTimeEndian,
+    format: Format,
+    version: u16,
+    address_size: u8,
+
+    strings: StringTable,
+    units: UnitTable,
+    unit_id: UnitId,
+    line_programs: LineProgramTable,
+    global_line_program: LineProgramId,
+    ranges: RangesTable,
+    unit_ranges: RangeList,
+    symbol_names: Vec<String>,
+
+    _dummy: PhantomData<&'tcx ()>,
+}
+
+impl<'a, 'tcx: 'a> DebugContext<'tcx> {
+    pub fn new(tcx: TyCtxt, address_size: u8) -> Self {
+        // TODO: this should be configurable
+        let version = 4;
+        let format = Format::Dwarf32;
+
+        // FIXME: how to get version when building out of tree?
+        // Normally this would use option_env!("CFG_VERSION").
+        let producer = format!("cranelift fn (rustc version {})", "unknown version");
+        let comp_dir = tcx.sess.working_dir.0.to_string_lossy().into_owned();
+        let name = match tcx.sess.local_crate_source_file {
+            Some(ref path) => path.to_string_lossy().into_owned(),
+            None => tcx.crate_name(LOCAL_CRATE).to_string(),
+        };
+
+        let mut units = UnitTable::default();
+        let mut strings = StringTable::default();
+        let mut line_programs = LineProgramTable::default();
+        let ranges = RangesTable::default();
+
+        let global_line_program = line_programs.add(LineProgram::new(
+            version,
+            address_size,
+            format,
+            1,
+            1,
+            -5,
+            14,
+            comp_dir.as_bytes(),
+            name.as_bytes(),
+            None,
+        ));
+
+        let unit_id = units.add(CompilationUnit::new(version, address_size, format));
+        {
+            let name = strings.add(&*name);
+            let comp_dir = strings.add(&*comp_dir);
+
+            let unit = units.get_mut(unit_id);
+            let root = unit.root();
+            let root = unit.get_mut(root);
+            root.set(
+                gimli::DW_AT_producer,
+                AttributeValue::StringRef(strings.add(producer)),
+            );
+            root.set(
+                gimli::DW_AT_language,
+                AttributeValue::Language(gimli::DW_LANG_Rust),
+            );
+            root.set(gimli::DW_AT_name, AttributeValue::StringRef(name));
+            root.set(gimli::DW_AT_comp_dir, AttributeValue::StringRef(comp_dir));
+            root.set(
+                gimli::DW_AT_stmt_list,
+                AttributeValue::LineProgramRef(global_line_program),
+            );
+            root.set(
+                gimli::DW_AT_low_pc,
+                AttributeValue::Address(Address::Absolute(0)),
+            );
+        }
+
+        DebugContext {
+            endian: target_endian(tcx),
+            format,
+            version,
+            address_size,
+
+            strings,
+            units,
+            unit_id,
+            line_programs,
+            global_line_program,
+            ranges,
+            unit_ranges: RangeList(Vec::new()),
+            symbol_names: Vec::new(),
+            _dummy: PhantomData,
+        }
+    }
+
+    fn emit_location(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, entry_id: UnitEntryId, span: Span) {
+        let loc = tcx.sess.source_map().lookup_char_pos(span.lo());
+
+        let unit = self.units.get_mut(self.unit_id);
+        let entry = unit.get_mut(entry_id);
+
+        let file_id = self.strings.add(loc.file.name.to_string());
+        entry.set(gimli::DW_AT_decl_file, AttributeValue::StringRef(file_id));
+        entry.set(
+            gimli::DW_AT_decl_line,
+            AttributeValue::Udata(loc.line as u64),
+        );
+        // FIXME: probably omit this
+        entry.set(
+            gimli::DW_AT_decl_column,
+            AttributeValue::Udata(loc.col.to_usize() as u64),
+        );
+    }
+
+    pub fn emit(&mut self, artifact: &mut Artifact) {
+        let unit_range_id = self.ranges.add(self.unit_ranges.clone());
+        let unit = self.units.get_mut(self.unit_id);
+        let root = unit.root();
+        let root = unit.get_mut(root);
+        root.set(
+            gimli::DW_AT_ranges,
+            AttributeValue::RangeListsRef(unit_range_id),
+        );
+
+        let mut debug_abbrev = DebugAbbrev::from(WriterRelocate::new(self));
+        let mut debug_info = DebugInfo::from(WriterRelocate::new(self));
+        let mut debug_str = DebugStr::from(WriterRelocate::new(self));
+        let mut debug_line = DebugLine::from(WriterRelocate::new(self));
+        let mut debug_ranges = DebugRanges::from(WriterRelocate::new(self));
+        let mut debug_rnglists = DebugRngLists::from(WriterRelocate::new(self));
+
+        let debug_line_offsets = self.line_programs.write(&mut debug_line).unwrap();
+        let debug_str_offsets = self.strings.write(&mut debug_str).unwrap();
+        let (debug_ranges_offsets, debug_rnglists_offsets) = self
+            .ranges
+            .write(
+                &mut debug_ranges,
+                &mut debug_rnglists,
+                self.format,
+                self.version,
+                self.address_size,
+            )
+            .unwrap();
+        self.units
+            .write(
+                &mut debug_abbrev,
+                &mut debug_info,
+                &debug_line_offsets,
+                &debug_ranges_offsets,
+                &debug_rnglists_offsets,
+                &debug_str_offsets,
+            )
+            .unwrap();
+
+        artifact
+            .declare_with(
+                SectionId::DebugAbbrev.name(),
+                Decl::DebugSection,
+                debug_abbrev.0.writer.into_vec(),
+            )
+            .unwrap();
+        artifact
+            .declare_with(
+                SectionId::DebugInfo.name(),
+                Decl::DebugSection,
+                debug_info.0.writer.into_vec(),
+            )
+            .unwrap();
+        artifact
+            .declare_with(
+                SectionId::DebugStr.name(),
+                Decl::DebugSection,
+                debug_str.0.writer.into_vec(),
+            )
+            .unwrap();
+        artifact
+            .declare_with(
+                SectionId::DebugLine.name(),
+                Decl::DebugSection,
+                debug_line.0.writer.into_vec(),
+            )
+            .unwrap();
+        artifact
+            .declare_with(
+                SectionId::DebugRanges.name(),
+                Decl::DebugSection,
+                debug_ranges.0.writer.into_vec(),
+            )
+            .unwrap();
+        artifact
+            .declare_with(
+                SectionId::DebugRngLists.name(),
+                Decl::DebugSection,
+                debug_rnglists.0.writer.into_vec(),
+            )
+            .unwrap();
+
+        for reloc in debug_abbrev.0.relocs {
+            artifact
+                .link_with(
+                    faerie::Link {
+                        from: SectionId::DebugAbbrev.name(),
+                        to: &reloc.name,
+                        at: u64::from(reloc.offset),
+                    },
+                    faerie::Reloc::Debug {
+                        size: reloc.size,
+                        addend: reloc.addend as i32,
+                    },
+                )
+                .expect("faerie relocation error");
+        }
+
+        for reloc in debug_info.0.relocs {
+            artifact
+                .link_with(
+                    faerie::Link {
+                        from: SectionId::DebugInfo.name(),
+                        to: &reloc.name,
+                        at: u64::from(reloc.offset),
+                    },
+                    faerie::Reloc::Debug {
+                        size: reloc.size,
+                        addend: reloc.addend as i32,
+                    },
+                )
+                .expect("faerie relocation error");
+        }
+
+        for reloc in debug_str.0.relocs {
+            artifact
+                .link_with(
+                    faerie::Link {
+                        from: SectionId::DebugStr.name(),
+                        to: &reloc.name,
+                        at: u64::from(reloc.offset),
+                    },
+                    faerie::Reloc::Debug {
+                        size: reloc.size,
+                        addend: reloc.addend as i32,
+                    },
+                )
+                .expect("faerie relocation error");
+        }
+
+        for reloc in debug_line.0.relocs {
+            artifact
+                .link_with(
+                    faerie::Link {
+                        from: SectionId::DebugLine.name(),
+                        to: &reloc.name,
+                        at: u64::from(reloc.offset),
+                    },
+                    faerie::Reloc::Debug {
+                        size: reloc.size,
+                        addend: reloc.addend as i32,
+                    },
+                )
+                .expect("faerie relocation error");
+        }
+
+        for reloc in debug_ranges.0.relocs {
+            artifact
+                .link_with(
+                    faerie::Link {
+                        from: SectionId::DebugRanges.name(),
+                        to: &reloc.name,
+                        at: u64::from(reloc.offset),
+                    },
+                    faerie::Reloc::Debug {
+                        size: reloc.size,
+                        addend: reloc.addend as i32,
+                    },
+                )
+                .expect("faerie relocation error");
+        }
+
+        for reloc in debug_rnglists.0.relocs {
+            artifact
+                .link_with(
+                    faerie::Link {
+                        from: SectionId::DebugRngLists.name(),
+                        to: &reloc.name,
+                        at: u64::from(reloc.offset),
+                    },
+                    faerie::Reloc::Debug {
+                        size: reloc.size,
+                        addend: reloc.addend as i32,
+                    },
+                )
+                .expect("faerie relocation error");
+        }
+    }
+
+    fn section_name(&self, id: SectionId) -> String {
+        id.name().to_string()
+    }
+}
+
+pub struct FunctionDebugContext<'a, 'tcx> {
+    debug_context: &'a mut DebugContext<'tcx>,
+    entry_id: UnitEntryId,
+    symbol: usize,
+}
+
+impl<'a, 'b, 'tcx: 'b> FunctionDebugContext<'a, 'tcx> {
+    pub fn new(
+        tcx: TyCtxt<'b, 'tcx, 'tcx>,
+        debug_context: &'a mut DebugContext<'tcx>,
+        mir: &Mir,
+        name: &str,
+        _sig: &Signature,
+    ) -> Self {
+        let symbol = debug_context.symbol_names.len();
+        debug_context.symbol_names.push(name.to_string());
+
+        let unit = debug_context.units.get_mut(debug_context.unit_id);
+        // FIXME: add to appropriate scope intead of root
+        let scope = unit.root();
+
+        let entry_id = unit.add(scope, gimli::DW_TAG_subprogram);
+        let entry = unit.get_mut(entry_id);
+        let name_id = debug_context.strings.add(name);
+        entry.set(
+            gimli::DW_AT_linkage_name,
+            AttributeValue::StringRef(name_id),
+        );
+
+        entry.set(
+            gimli::DW_AT_low_pc,
+            AttributeValue::Address(Address::Relative { symbol, addend: 0 }),
+        );
+
+        debug_context.emit_location(tcx, entry_id, mir.span);
+
+        FunctionDebugContext {
+            debug_context,
+            entry_id,
+            symbol,
+        }
+    }
+
+    pub fn define(
+        &mut self,
+        tcx: TyCtxt,
+        //module: &mut Module<impl Backend>,
+        size: u32,
+        context: &Context,
+        isa: &cranelift::codegen::isa::TargetIsa,
+        spans: &[Span],
+    ) {
+        let unit = self.debug_context.units.get_mut(self.debug_context.unit_id);
+        // FIXME: add to appropriate scope intead of root
+        let entry = unit.get_mut(self.entry_id);
+        let mut size_array = [0; 8];
+        byteorder::LittleEndian::write_u64(&mut size_array, size as u64);
+        entry.set(gimli::DW_AT_high_pc, AttributeValue::Data8(size_array));
+
+        self.debug_context.unit_ranges.0.push(Range {
+            begin: Address::Relative {
+                symbol: self.symbol,
+                addend: 0,
+            },
+            end: Address::Relative {
+                symbol: self.symbol,
+                addend: size as i64,
+            },
+        });
+
+        let line_program = self
+            .debug_context
+            .line_programs
+            .get_mut(self.debug_context.global_line_program);
+
+        line_program.begin_sequence(Some(Address::Relative {
+            symbol: self.symbol,
+            addend: 0,
+        }));
+
+        let encinfo = isa.encoding_info();
+        let func = &context.func;
+        let mut ebbs = func.layout.ebbs().collect::<Vec<_>>();
+        ebbs.sort_by_key(|ebb| func.offsets[*ebb]); // Ensure inst offsets always increase
+        for ebb in ebbs {
+            for (offset, inst, _size) in func.inst_offsets(ebb, &encinfo) {
+                let srcloc = func.srclocs[inst];
+                if !srcloc.is_default() {
+                    let span = spans[srcloc.bits() as usize];
+                    let loc = tcx.sess.source_map().lookup_char_pos(span.lo());
+                    let file = loc.file.name.to_string();
+                    let file = ::std::path::Path::new(&file);
+                    let dir_id = line_program
+                        .add_directory(file.parent().unwrap().to_str().unwrap().as_bytes());
+                    let file_id = line_program.add_file(
+                        file.file_name().unwrap().to_str().unwrap().as_bytes(),
+                        dir_id,
+                        None,
+                    );
+                    line_program.row().file = file_id;
+                    //tcx.sess
+                    //    .warn(&format!("srcloc {} {}:{}:{}", offset, file, loc.line, loc.col.to_usize()));
+                    line_program.row().address_offset = offset as u64;
+                    line_program.row().line = loc.line as u64;
+                    line_program.generate_row();
+                }
+            }
+        }
+
+        let address_offset = line_program.row().address_offset;
+        line_program.end_sequence(address_offset);
+    }
+}
+
+struct WriterRelocate<'a, 'tcx> {
+    ctx: &'a DebugContext<'tcx>,
+    relocs: Vec<DebugReloc>,
+    writer: EndianVec<RunTimeEndian>,
+}
+
+impl<'a, 'tcx> WriterRelocate<'a, 'tcx> {
+    fn new(ctx: &'a DebugContext<'tcx>) -> Self {
+        WriterRelocate {
+            ctx,
+            relocs: Vec::new(),
+            writer: EndianVec::new(ctx.endian),
+        }
+    }
+}
+
+impl<'a, 'tcx> Writer for WriterRelocate<'a, 'tcx> {
+    type Endian = RunTimeEndian;
+
+    fn endian(&self) -> Self::Endian {
+        self.writer.endian()
+    }
+
+    fn len(&self) -> usize {
+        self.writer.len()
+    }
+
+    fn write(&mut self, bytes: &[u8]) -> Result<()> {
+        self.writer.write(bytes)
+    }
+
+    fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
+        self.writer.write_at(offset, bytes)
+    }
+
+    fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
+        match address {
+            Address::Absolute(val) => self.write_word(val, size),
+            Address::Relative { symbol, addend } => {
+                let offset = self.len() as u64;
+                self.relocs.push(DebugReloc {
+                    offset: offset as u32,
+                    size,
+                    name: self.ctx.symbol_names[symbol].clone(),
+                    addend: addend as i64,
+                });
+                self.write_word(0, size)
+            }
+        }
+    }
+
+    fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> {
+        let offset = self.len() as u32;
+        let name = self.ctx.section_name(section);
+        self.relocs.push(DebugReloc {
+            offset,
+            size,
+            name,
+            addend: val as i64,
+        });
+        self.write_word(0, size)
+    }
+
+    fn write_offset_at(
+        &mut self,
+        offset: usize,
+        val: usize,
+        section: SectionId,
+        size: u8,
+    ) -> Result<()> {
+        let name = self.ctx.section_name(section);
+        self.relocs.push(DebugReloc {
+            offset: offset as u32,
+            size,
+            name,
+            addend: val as i64,
+        });
+        self.write_word_at(offset, 0, size)
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 7df9b6ae42e..7b0e4d231d6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -20,7 +20,7 @@ use std::sync::mpsc;
 use rustc::dep_graph::DepGraph;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::{
-    config::{OutputFilenames, OutputType},
+    config::{DebugInfo, OutputFilenames, OutputType},
     CompileIncomplete,
 };
 use rustc::ty::query::Providers;
@@ -43,6 +43,7 @@ mod archive;
 mod base;
 mod common;
 mod constant;
+mod debuginfo;
 mod intrinsics;
 mod link;
 mod link_copied;
@@ -59,7 +60,7 @@ mod prelude {
     pub use std::collections::{HashMap, HashSet};
 
     pub use syntax::ast::{FloatTy, IntTy, UintTy};
-    pub use syntax::source_map::DUMMY_SP;
+    pub use syntax::source_map::{DUMMY_SP, Span, Pos};
 
     pub use rustc::bug;
     pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@@ -85,17 +86,21 @@ mod prelude {
     pub use rustc_codegen_ssa::traits::*;
 
     pub use cranelift::codegen::ir::{
-        condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, StackSlot,
+        condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, StackSlot, SourceLoc,
     };
     pub use cranelift::codegen::isa::CallConv;
     pub use cranelift::codegen::Context;
     pub use cranelift::prelude::*;
-    pub use cranelift_module::{Backend, DataContext, DataId, FuncId, Linkage, Module};
+    pub use cranelift_module::{
+        self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage,
+        Module,
+    };
     pub use cranelift_simplejit::{SimpleJITBackend, SimpleJITBuilder};
 
     pub use crate::abi::*;
     pub use crate::base::{trans_operand, trans_place};
     pub use crate::common::*;
+    pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
     pub use crate::trap::*;
     pub use crate::unimpl::{unimpl, with_unimpl_span};
     pub use crate::{Caches, CodegenCx};
@@ -120,15 +125,21 @@ pub struct CodegenCx<'a, 'clif, 'tcx, B: Backend + 'static> {
     module: &'clif mut Module<B>,
     ccx: ConstantCx,
     caches: Caches<'tcx>,
+    debug_context: Option<&'clif mut DebugContext<'tcx>>,
 }
 
 impl<'a, 'clif, 'tcx, B: Backend + 'static> CodegenCx<'a, 'clif, 'tcx, B> {
-    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, module: &'clif mut Module<B>) -> Self {
+    fn new(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        module: &'clif mut Module<B>,
+        debug_context: Option<&'clif mut DebugContext<'tcx>>,
+    ) -> Self {
         CodegenCx {
             tcx,
             module,
             ccx: ConstantCx::default(),
             caches: Caches::default(),
+            debug_context,
         }
     }
 
@@ -225,7 +236,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
                 .declare_function("main", Linkage::Import, &sig)
                 .unwrap();
 
-            codegen_cgus(tcx, &mut jit_module, &mut log);
+            codegen_cgus(tcx, &mut jit_module, &mut None, &mut log);
             crate::allocator::codegen(tcx.sess, &mut jit_module);
             jit_module.finalize_definitions();
 
@@ -261,9 +272,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
                 module
             };
 
-            let emit_module = |name: &str, kind: ModuleKind, mut module: Module<FaerieBackend>| {
+            let emit_module = |name: &str, kind: ModuleKind, mut module: Module<FaerieBackend>, debug: Option<DebugContext>| {
                 module.finalize_definitions();
-                let artifact = module.finish().artifact;
+                let mut artifact = module.finish().artifact;
+
+                if let Some(mut debug) = debug {
+                    debug.emit(&mut artifact);
+                }
 
                 let tmp_file = tcx
                     .output_filenames(LOCAL_CRATE)
@@ -281,7 +296,14 @@ impl CodegenBackend for CraneliftCodegenBackend {
 
             let mut faerie_module = new_module("some_file".to_string());
 
-            codegen_cgus(tcx, &mut faerie_module, &mut log);
+            let mut debug = if tcx.sess.opts.debuginfo != DebugInfo::None {
+                let debug = DebugContext::new(tcx, faerie_module.target_config().pointer_type().bytes() as u8);
+                Some(debug)
+            } else {
+                None
+            };
+
+            codegen_cgus(tcx, &mut faerie_module, &mut debug, &mut log);
 
             tcx.sess.abort_if_errors();
 
@@ -291,9 +313,9 @@ impl CodegenBackend for CraneliftCodegenBackend {
 
             return Box::new(CodegenResults {
                 crate_name: tcx.crate_name(LOCAL_CRATE),
-                modules: vec![emit_module("dummy_name", ModuleKind::Regular, faerie_module)],
+                modules: vec![emit_module("dummy_name", ModuleKind::Regular, faerie_module, debug)],
                 allocator_module: if created_alloc_shim {
-                    Some(emit_module("allocator_shim", ModuleKind::Allocator, allocator_module))
+                    Some(emit_module("allocator_shim", ModuleKind::Allocator, allocator_module, None))
                 } else {
                     None
                 },
@@ -372,6 +394,7 @@ fn build_isa(sess: &Session) -> Box<isa::TargetIsa + 'static> {
 fn codegen_cgus<'a, 'tcx: 'a>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     module: &mut Module<impl Backend + 'static>,
+    debug: &mut Option<DebugContext<'tcx>>,
     log: &mut Option<File>,
 ) {
     let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
@@ -382,7 +405,7 @@ fn codegen_cgus<'a, 'tcx: 'a>(
         .map(|(&mono_item, &(linkage, vis))| (mono_item, (linkage, vis)))
         .collect::<FxHashMap<_, (_, _)>>();
 
-    codegen_mono_items(tcx, module, log, mono_items);
+    codegen_mono_items(tcx, module, debug.as_mut(), log, mono_items);
 
     crate::main_shim::maybe_create_entry_wrapper(tcx, module);
 }
@@ -390,10 +413,11 @@ fn codegen_cgus<'a, 'tcx: 'a>(
 fn codegen_mono_items<'a, 'tcx: 'a>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     module: &mut Module<impl Backend + 'static>,
+    debug_context: Option<&mut DebugContext<'tcx>>,
     log: &mut Option<File>,
     mono_items: FxHashMap<MonoItem<'tcx>, (RLinkage, Visibility)>,
 ) {
-    let mut cx = CodegenCx::new(tcx, module);
+    let mut cx = CodegenCx::new(tcx, module, debug_context);
     time("codegen mono items", move || {
         for (mono_item, (linkage, vis)) in mono_items {
             unimpl::try_unimpl(tcx, log, || {
diff --git a/test.sh b/test.sh
index d03b48c96bc..1782df6113d 100755
--- a/test.sh
+++ b/test.sh
@@ -10,16 +10,16 @@ rm -r target/out || true
 mkdir -p target/out/clif
 
 echo "[BUILD] mini_core"
-$RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib
+$RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib -g
 
 echo "[BUILD] example"
-$RUSTC example/example.rs --crate-type lib
+$RUSTC example/example.rs --crate-type lib -g
 
 echo "[JIT] mini_core_hello_world"
 SHOULD_RUN=1 $RUSTC --crate-type bin example/mini_core_hello_world.rs --cfg jit
 
 echo "[AOT] mini_core_hello_world"
-$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin
+$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g
 sh -c ./target/out/mini_core_hello_world || true
 
 echo "[BUILD] sysroot"
@@ -31,7 +31,7 @@ time ./build_sysroot/build_sysroot.sh
 #./target/out/alloc_example
 
 echo "[BUILD] mod_bench"
-$RUSTC --sysroot ./build_sysroot/sysroot example/mod_bench.rs --crate-type bin
+$RUSTC --sysroot ./build_sysroot/sysroot example/mod_bench.rs --crate-type bin -g
 
 echo "[BUILD] sysroot in release mode"
 ./build_sysroot/build_sysroot.sh --release