commit 4d615dba0e913d807b38e893ec51e2bf6ea40287 Author: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun Jun 17 18:05:11 2018 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..02ca9dcf64f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +*.rlib diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000000..e215ad03431 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,147 @@ +[[package]] +name = "cretonne" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cretonne-codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cretonne-frontend 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cretonne-codegen" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cretonne-entity 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cretonne-entity" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cretonne-frontend" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cretonne-codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dtoa" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "failure" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_codegen_cretonne" +version = "0.1.0" +dependencies = [ + "cretonne 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_json" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "target-lexicon" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum cretonne 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83e1f8d40914cb726d41a49df9554f200b47f36a03c46e5d6044e9dc8a8a47cd" +"checksum cretonne-codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "312ba69a70bebc54789bd0e28414987b5bcd1173263f6afbd0ee8519b84da4ac" +"checksum cretonne-entity 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0be57790fb6db92704951e37981f5e0121e7bfa077c7b48177317bf63795ba4" +"checksum cretonne-frontend 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "14b0fe88b2bc5b71df2ce460761063da21731926e6b554c84d8b937de6640875" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" +"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" +"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a2d9a9ac5120e0f768801ca2b58ad6eec929dc9d1d616c162f208869c2ce95" +"checksum serde_json 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "fc97cccc2959f39984524026d760c08ef0dd5f0f5948c8d31797dbfae458c875" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" +"checksum target-lexicon 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71b0a95ba4eff593189d912039fba46ce6ca1876ea6c16830e15340919d0a250" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000000..72859b0d7cc --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rustc_codegen_cretonne" +version = "0.1.0" +authors = ["bjorn3 "] + +[lib] +crate-type = ["dylib"] + +[dependencies] +cretonne = "0.11.0" diff --git a/build.sh b/build.sh new file mode 100755 index 00000000000..5193ef20a11 --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +cargo build || exit 1 + +rustc -Zcodegen-backend=$(pwd)/target/debug/librustc_codegen_cretonne.dylib example.rs --crate-type lib diff --git a/example.rs b/example.rs new file mode 100644 index 00000000000..0962f150635 --- /dev/null +++ b/example.rs @@ -0,0 +1,44 @@ +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized {} + +#[lang="copy"] +trait Copy {} + +#[lang="freeze"] +trait Freeze {} + +#[lang="mul"] +trait Mul { + type Output; + + #[must_use] + fn mul(self, rhs: RHS) -> Self::Output; +} + +impl Mul for u8 { + type Output = u8; + + fn mul(self, rhs: u8) -> u8 { + self * rhs + } +} + +#[lang="panic"] +fn panic(_expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { + loop {} +} + +fn abc(a: u8) -> u8 { + a * 2 +} + +fn bcd(b: bool, a: u8) -> u8 { + if b { + a * 2 + } else { + a * 3 + } +} \ No newline at end of file diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 00000000000..bf867e0ae5b --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly diff --git a/src/base.rs b/src/base.rs new file mode 100644 index 00000000000..e8356d89f79 --- /dev/null +++ b/src/base.rs @@ -0,0 +1,349 @@ +use syntax::ast::{IntTy, UintTy}; +use rustc_mir::monomorphize::MonoItem; + +use cretonne::prelude::*; +use cretonne::codegen::ir::{ + ExternalName, + function::Function, +}; + +use std::any::Any; +use std::collections::HashMap; + +use prelude::*; + +pub struct Translated { + f: Function, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +struct Variable(Local); + +impl EntityRef for Variable { + fn new(u: usize) -> Self { + Variable(Local::new(u)) + } + + fn index(self) -> usize { + self.0.index() + } +} + +enum CValue { + ByRef(Value), + ByVal(Value), +} + +impl CValue { + fn force_stack<'a, 'tcx: 'a>(self, ccx: &mut CodegenCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Value { + match self { + CValue::ByRef(value) => value, + CValue::ByVal(value) => { + let layout = ccx.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); + let stack_slot = ccx.bcx.create_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: layout.size.bytes() as u32, + offset: None, + }); + ccx.bcx.ins().stack_store(value, stack_slot, 0); + ccx.bcx.ins().stack_addr(types::I64, stack_slot, 0) + } + } + } + + fn load_value<'a, 'tcx: 'a>(self, ccx: &mut CodegenCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Value { + match self { + CValue::ByRef(value) => { + let cton_ty = cton_type_from_ty(ty); + ccx.bcx.ins().load(cton_ty, MemFlags::new(), value, 0) + } + CValue::ByVal(value) => value, + } + } +} + +pub fn trans_crate<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Box { + let link_meta = ::build_link_meta(tcx.crate_hash(LOCAL_CRATE)); + let metadata = tcx.encode_metadata(&link_meta); + + let mut translated_mono_items = Vec::new(); + + for mono_item in + collector::collect_crate_mono_items( + tcx, + collector::MonoItemCollectionMode::Eager + ).0 { + match mono_item { + MonoItem::Fn(Instance { + def: InstanceDef::Item(def_id), + substs, + }) => { + let sig = tcx.fn_sig(def_id); + let sig = tcx.subst_and_normalize_erasing_regions(substs, ParamEnv::reveal_all(), &sig); + let mut f = Function::with_name_signature(ext_name_from_did(def_id), cton_sig_from_fn_sig(sig.skip_binder())); + + trans_fn(tcx, &mut f, def_id, substs); + + let mut mir = ::std::io::Cursor::new(Vec::new()); + ::rustc_mir::util::write_mir_pretty(tcx, Some(def_id), &mut mir).unwrap(); + let mut cton = String::new(); + ::cretonne::codegen::write_function(&mut cton, &f, None).unwrap(); + tcx.sess.warn(&format!("{:?}:\n\n{}\n\n{}", def_id, String::from_utf8_lossy(&mir.into_inner()), cton)); + + translated_mono_items.push(Translated { + f, + }); + } + _ => {} + } + } + + Box::new(::OngoingCodegen { + metadata: metadata, + translated_mono_items, + crate_name: tcx.crate_name(LOCAL_CRATE), + }) +} + +struct CodegenCtxt<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + bcx: FunctionBuilder<'a, Variable>, + mir: &'tcx Mir<'tcx>, + ebb_map: HashMap, + args_map: HashMap, +} + +impl<'f, 'tcx> CodegenCtxt<'f, 'tcx> { + fn get_ebb(&self, bb: BasicBlock) -> Ebb { + *self.ebb_map.get(&bb).unwrap() + } + + fn get_local(&mut self, local: Local) -> Value { + match self.mir.local_kind(local) { + LocalKind::Arg => *self.args_map.get(&local).unwrap(), + LocalKind::ReturnPointer => *self.args_map.get(&RETURN_PLACE).unwrap(), + LocalKind::Temp | LocalKind::Var => self.bcx.use_var(Variable(local)), + } + } +} + +fn trans_fn<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, f: &mut Function, def_id: DefId, substs: &Substs) { + let mir = tcx.optimized_mir(def_id); + let mut func_ctx = FunctionBuilderContext::new(); + let mut bcx: FunctionBuilder = FunctionBuilder::new(f, &mut func_ctx); + + let start_ebb = bcx.create_ebb(); + bcx.switch_to_block(start_ebb); + let mut ebb_map: HashMap = HashMap::new(); + for (bb, _bb_data) in mir.basic_blocks().iter_enumerated() { + ebb_map.insert(bb, bcx.create_ebb()); + } + + let mut args_map: HashMap = HashMap::new(); + for arg in Some(RETURN_PLACE).into_iter().chain(mir.args_iter()) { + let ty = types::I64; + args_map.insert(arg, bcx.append_ebb_param(start_ebb, ty)); + } + + for local in mir.vars_and_temps_iter() { + let layout = tcx.layout_of(ParamEnv::reveal_all().and(mir.local_decls[local].ty)).unwrap(); + let stack_slot = bcx.create_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: layout.size.bytes() as u32, + offset: None, + }); + let ty = types::I64; + bcx.declare_var(Variable(local), ty); + let val = bcx.ins().stack_addr(ty, stack_slot, 0); + bcx.def_var(Variable(local), val); + } + bcx.ins().jump(*ebb_map.get(&START_BLOCK).unwrap(), &[]); + + let mut ccx = CodegenCtxt { + tcx, + bcx, + mir, + ebb_map, + args_map, + }; + let ccx = &mut ccx; + + for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { + let ebb = ccx.get_ebb(bb); + ccx.bcx.switch_to_block(ebb); + + for stmt in &bb_data.statements { + trans_stmt(ccx, stmt); + } + + match &bb_data.terminator().kind { + TerminatorKind::Goto { target } => { + let ebb = ccx.get_ebb(*target); + ccx.bcx.ins().jump(ebb, &[]); + } + TerminatorKind::Return => { + ccx.bcx.ins().return_(&[]); + } + TerminatorKind::Assert { cond, expected, msg, target, cleanup } => { + let cond_ty = cond.ty(&ccx.mir.local_decls, ccx.tcx); + let cond = trans_operand(ccx, cond).load_value(ccx, cond_ty); + let target = ccx.get_ebb(*target); + if *expected { + ccx.bcx.ins().brz(cond, target, &[]); + } else { + ccx.bcx.ins().brnz(cond, target, &[]); + } + ccx.bcx.ins().trap(TrapCode::User(!0)); + } + + TerminatorKind::SwitchInt { discr, switch_ty, values, targets } => { + let discr_ty = discr.ty(&ccx.mir.local_decls, ccx.tcx); + let discr = trans_operand(ccx, discr).load_value(ccx, discr_ty); + let mut jt_data = JumpTableData::new(); + for (i, value) in values.iter().enumerate() { + let ebb = ccx.get_ebb(targets[i]); + jt_data.set_entry(*value as usize, ebb); + } + let mut jump_table = ccx.bcx.create_jump_table(jt_data); + ccx.bcx.ins().br_table(discr, jump_table); + let otherwise_ebb = ccx.get_ebb(targets[targets.len() - 1]); + ccx.bcx.ins().jump(otherwise_ebb, &[]); + } + _ => { + unimplemented!(); + } + } + } + + ccx.bcx.seal_all_blocks(); + ccx.bcx.finalize(); +} + +fn trans_stmt<'a, 'tcx: 'a>(ccx: &mut CodegenCtxt<'a, 'tcx>, stmt: &Statement<'tcx>) { + match &stmt.kind { + StatementKind::Assign(place, rval) => { + let ty = place.ty(&ccx.mir.local_decls, ccx.tcx); + let lval = trans_place(ccx, place); + let rval = trans_rval(ccx, rval); + do_memcpy(ccx, lval, ty); + } + StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => {} + _ => unimplemented!("stmt {:?}", stmt), + } +} + +fn trans_place<'a, 'tcx: 'a>(ccx: &mut CodegenCtxt<'a, 'tcx>, place: &Place<'tcx>) -> Value { + match place { + Place::Local(local) => ccx.get_local(*local), + Place::Projection(projection) => { + let base = trans_place(ccx, &projection.base); + match projection.elem { + ProjectionElem::Field(field, ty) => { + let layout = ccx.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); + ccx.bcx.ins().iconst(types::I64, 0) // unimplemented ===================================================== + } + _ => unimplemented!("projection {:?}", projection), + } + } + place => unimplemented!("place {:?}", place), + } +} + +fn trans_rval<'a, 'tcx: 'a>(ccx: &mut CodegenCtxt<'a, 'tcx>, rval: &Rvalue<'tcx>) -> Value { + match rval { + Rvalue::Use(operand) => { + let operand_ty = operand.ty(&ccx.mir.local_decls, ccx.tcx); + trans_operand(ccx, operand).force_stack(ccx, operand_ty) + }, + Rvalue::CheckedBinaryOp(bin_op, lhs, rhs) => { + match bin_op { + BinOp::Mul => { + let ty = lhs.ty(&ccx.mir.local_decls, ccx.tcx); + let lhs_ty = lhs.ty(&ccx.mir.local_decls, ccx.tcx); + let lhs = trans_operand(ccx, lhs).load_value(ccx, lhs_ty); + let rhs_ty = rhs.ty(&ccx.mir.local_decls, ccx.tcx); + let rhs = trans_operand(ccx, rhs).load_value(ccx, rhs_ty); + match ty.sty { + TypeVariants::TyUint(_) => { + ccx.bcx.ins().imul(lhs, rhs) + } + _ => unimplemented!(), + } + } + bin_op => unimplemented!("checked bin op {:?} {:?} {:?}", bin_op, lhs, rhs), + } + } + rval => unimplemented!("{:?}", rval), + } +} + +fn trans_operand<'a, 'tcx>(ccx: &mut CodegenCtxt<'a, 'tcx>, operand: &Operand<'tcx>) -> CValue { + match operand { + Operand::Move(place) => CValue::ByRef(trans_place(ccx, place)), + Operand::Constant(const_) => { + match const_.literal { + Literal::Value { value } => { + let layout = ccx.tcx.layout_of(ParamEnv::empty().and(const_.ty)).unwrap(); + let bits = value.to_scalar().unwrap().to_bits(layout.size).unwrap(); + match const_.ty.sty { + TypeVariants::TyUint(_) => { + let iconst = ccx.bcx.ins().iconst(cton_type_from_ty(const_.ty), bits as u64 as i64); + CValue::ByVal(iconst) + } + _ => unimplemented!(), + } + } + _ => unimplemented!() + } + } + operand => unimplemented!("operand {:?}", operand), + } +} + +fn ext_name_from_did(def_id: DefId) -> ExternalName { + ExternalName::user(def_id.krate.as_u32(), def_id.index.as_raw_u32()) +} + +fn cton_sig_from_fn_sig(sig: &FnSig) -> Signature { + let inputs = sig.inputs(); + let output = sig.output(); + assert!(!sig.variadic, "Variadic function are not yet supported"); + let call_conv = match sig.abi { + _ => CallConv::SystemV, + }; + Signature { + params: Some(types::I64).into_iter() // First param is palce to put return val + .chain(inputs.into_iter().map(|_| types::I64)) + .map(AbiParam::new).collect(), + returns: vec![], + call_conv, + argument_bytes: None, + } +} + +fn cton_type_from_ty(ty: Ty) -> types::Type { + match ty.sty { + TypeVariants::TyBool => types::B1, + TypeVariants::TyUint(size) => { + match size { + UintTy::U8 => types::I8, + UintTy::U16 => types::I16, + UintTy::U32 => types::I32, + UintTy::U64 => types::I64, + UintTy::U128 => unimplemented!(), + UintTy::Usize => unimplemented!(), + } + } + TypeVariants::TyInt(size) => { + match size { + IntTy::I8 => types::I8, + IntTy::I16 => types::I16, + IntTy::I32 => types::I32, + IntTy::I64 => types::I64, + IntTy::I128 => unimplemented!(), + IntTy::Isize => unimplemented!(), + } + } + _ => unimplemented!("Cton type from {:?}", ty), + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000000..5389c0b9ec9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,176 @@ +#![feature(rustc_private)] + +extern crate syntax; +extern crate rustc; +extern crate rustc_mir; +extern crate rustc_codegen_utils; +extern crate rustc_incremental; +extern crate rustc_data_structures; + +extern crate cretonne; + +use syntax::symbol::Symbol; +use rustc::session::{ + CompileIncomplete, + config::{ + CrateType, + OutputFilenames, + }, +}; +use rustc::middle::cstore::{MetadataLoader, EncodedMetadata}; +use rustc::dep_graph::DepGraph; +use rustc::ty::maps::Providers; +use rustc_codegen_utils::codegen_backend::{CodegenBackend, NoLlvmMetadataLoader}; +use rustc_codegen_utils::link::{out_filename, build_link_meta}; + +use std::any::Any; +use std::sync::{mpsc, Arc}; +use std::fs::File; +use std::io::Write; + +mod base; + +mod prelude { + pub use rustc::session::Session; + pub use rustc::hir::def_id::{DefId, LOCAL_CRATE}; + pub use rustc::ty::{TyCtxt, Ty, TypeVariants, Instance, InstanceDef, ParamEnv, FnSig, subst::Substs}; + pub use rustc::mir::*; + pub use rustc_mir::monomorphize::collector; + pub use rustc_data_structures::{ + sync::Lrc, + indexed_vec::Idx, + }; +} + +use prelude::*; + +struct CretonneCodegenBackend(()); + +struct OngoingCodegen { + metadata: EncodedMetadata, + translated_mono_items: Vec, + crate_name: Symbol, +} + +impl CretonneCodegenBackend { + fn new() -> Box { + Box::new(CretonneCodegenBackend(())) + } +} + +impl CodegenBackend for CretonneCodegenBackend { + fn init(&self, sess: &Session) { + for cty in sess.opts.crate_types.iter() { + match *cty { + CrateType::CrateTypeRlib | CrateType::CrateTypeDylib | + CrateType::CrateTypeExecutable => {}, + _ => { + sess.parse_sess.span_diagnostic.warn( + &format!("LLVM unsupported, so output type {} is not supported", cty) + ); + }, + } + } + } + + fn metadata_loader(&self) -> Box { + Box::new(NoLlvmMetadataLoader) + } + + fn provide(&self, providers: &mut Providers) { + rustc_codegen_utils::symbol_names::provide(providers); + + providers.target_features_whitelist = |_tcx, _cnum| { + /*Lrc::new(rustc_codegen_utils::llvm_target_features::all_known_features() + .map(|(a, b)| (a.to_string(), b.map(|s| s.to_string()))) + .collect())*/ + Lrc::new(Default::default()) + }; + providers.is_reachable_non_generic = |_tcx, _defid| true; + providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new()); + providers.wasm_custom_sections = |_tcx, _crate| Lrc::new(Vec::new()); + } + fn provide_extern(&self, providers: &mut Providers) { + providers.is_reachable_non_generic = |_tcx, _defid| true; + } + + fn codegen_crate<'a, 'tcx>( + &self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + _rx: mpsc::Receiver> + ) -> Box { + use rustc_mir::monomorphize::item::MonoItem; + + rustc_codegen_utils::check_for_rustc_errors_attr(tcx); + rustc_codegen_utils::symbol_names_test::report_symbol_names(tcx); + rustc_incremental::assert_dep_graph(tcx); + rustc_incremental::assert_module_sources::assert_module_sources(tcx); + rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, + collector::collect_crate_mono_items( + tcx, + collector::MonoItemCollectionMode::Eager + ).0.iter() + ); + //::rustc::middle::dependency_format::calculate(tcx); + let _ = tcx.link_args(LOCAL_CRATE); + let _ = tcx.native_libraries(LOCAL_CRATE); + for mono_item in + collector::collect_crate_mono_items( + tcx, + collector::MonoItemCollectionMode::Eager + ).0 { + match mono_item { + MonoItem::Fn(inst) => { + let def_id = inst.def_id(); + if def_id.is_local() { + let _ = inst.def.is_inline(tcx); + let _ = tcx.codegen_fn_attrs(def_id); + } + } + _ => {} + } + } + tcx.sess.abort_if_errors(); + + base::trans_crate(tcx) + } + + fn join_codegen_and_link( + &self, + ongoing_codegen: Box, + sess: &Session, + _dep_graph: &DepGraph, + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete> { + if true { + unimplemented!(); + } + + let ongoing_codegen = ongoing_codegen.downcast::() + .expect("Expected MetadataOnlyCodegenBackend's OngoingCodegen, found Box"); + for &crate_type in sess.opts.crate_types.iter() { + if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib { + continue; + } + let output_name = + out_filename(sess, crate_type, &outputs, &ongoing_codegen.crate_name.as_str()); + let metadata = &ongoing_codegen.metadata.raw_data; + let mut file = File::create(&output_name).unwrap(); + file.write_all(metadata).unwrap(); + } + + sess.abort_if_errors(); + if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib) + && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) + { + sess.fatal("Executables are not supported by the metadata-only backend."); + } + Ok(()) + } +} + +/// This is the entrypoint for a hot plugged rustc_codegen_cretonne +#[no_mangle] +pub fn __rustc_codegen_backend() -> Box { + CretonneCodegenBackend::new() +} \ No newline at end of file