Implement line debuginfo

This commit is contained in:
bjorn3 2019-01-17 18:07:27 +01:00
parent 9e609db886
commit 09c4569c87
10 changed files with 691 additions and 19 deletions

42
Cargo.lock generated
View file

@ -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"

View file

@ -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

35
abc.cpp Normal file
View file

@ -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;
}

View file

@ -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;

BIN
mini_core_hello_world Executable file

Binary file not shown.

View file

@ -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

View file

@ -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));
}
}

529
src/debuginfo.rs Normal file
View file

@ -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)
}
}

View file

@ -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, || {

View file

@ -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