summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_ssa/src/mono_item.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mono_item.rs')
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
new file mode 100644
index 000000000..5006a2157
--- /dev/null
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -0,0 +1,147 @@
+use crate::base;
+use crate::common;
+use crate::traits::*;
+use rustc_hir as hir;
+use rustc_middle::mir::mono::MonoItem;
+use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::ty;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::Instance;
+
+pub trait MonoItemExt<'a, 'tcx> {
+ fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
+ fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
+ &self,
+ cx: &'a Bx::CodegenCx,
+ linkage: Linkage,
+ visibility: Visibility,
+ );
+ fn to_raw_string(&self) -> String;
+}
+
+impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
+ fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
+ debug!(
+ "BEGIN IMPLEMENTING '{} ({})' in cgu {}",
+ self,
+ self.to_raw_string(),
+ cx.codegen_unit().name()
+ );
+
+ match *self {
+ MonoItem::Static(def_id) => {
+ cx.codegen_static(def_id, cx.tcx().is_mutable_static(def_id));
+ }
+ MonoItem::GlobalAsm(item_id) => {
+ let item = cx.tcx().hir().item(item_id);
+ if let hir::ItemKind::GlobalAsm(ref asm) = item.kind {
+ let operands: Vec<_> = asm
+ .operands
+ .iter()
+ .map(|(op, op_sp)| match *op {
+ hir::InlineAsmOperand::Const { ref anon_const } => {
+ let anon_const_def_id =
+ cx.tcx().hir().local_def_id(anon_const.hir_id).to_def_id();
+ let const_value =
+ cx.tcx().const_eval_poly(anon_const_def_id).unwrap_or_else(
+ |_| span_bug!(*op_sp, "asm const cannot be resolved"),
+ );
+ let ty = cx
+ .tcx()
+ .typeck_body(anon_const.body)
+ .node_type(anon_const.hir_id);
+ let string = common::asm_const_to_str(
+ cx.tcx(),
+ *op_sp,
+ const_value,
+ cx.layout_of(ty),
+ );
+ GlobalAsmOperandRef::Const { string }
+ }
+ hir::InlineAsmOperand::SymFn { ref anon_const } => {
+ let ty = cx
+ .tcx()
+ .typeck_body(anon_const.body)
+ .node_type(anon_const.hir_id);
+ let instance = match ty.kind() {
+ &ty::FnDef(def_id, substs) => Instance::new(def_id, substs),
+ _ => span_bug!(*op_sp, "asm sym is not a function"),
+ };
+
+ GlobalAsmOperandRef::SymFn { instance }
+ }
+ hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
+ GlobalAsmOperandRef::SymStatic { def_id }
+ }
+ hir::InlineAsmOperand::In { .. }
+ | hir::InlineAsmOperand::Out { .. }
+ | hir::InlineAsmOperand::InOut { .. }
+ | hir::InlineAsmOperand::SplitInOut { .. } => {
+ span_bug!(*op_sp, "invalid operand type for global_asm!")
+ }
+ })
+ .collect();
+
+ cx.codegen_global_asm(asm.template, &operands, asm.options, asm.line_spans);
+ } else {
+ span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
+ }
+ }
+ MonoItem::Fn(instance) => {
+ base::codegen_instance::<Bx>(&cx, instance);
+ }
+ }
+
+ debug!(
+ "END IMPLEMENTING '{} ({})' in cgu {}",
+ self,
+ self.to_raw_string(),
+ cx.codegen_unit().name()
+ );
+ }
+
+ fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
+ &self,
+ cx: &'a Bx::CodegenCx,
+ linkage: Linkage,
+ visibility: Visibility,
+ ) {
+ debug!(
+ "BEGIN PREDEFINING '{} ({})' in cgu {}",
+ self,
+ self.to_raw_string(),
+ cx.codegen_unit().name()
+ );
+
+ let symbol_name = self.symbol_name(cx.tcx()).name;
+
+ debug!("symbol {}", &symbol_name);
+
+ match *self {
+ MonoItem::Static(def_id) => {
+ cx.predefine_static(def_id, linkage, visibility, &symbol_name);
+ }
+ MonoItem::Fn(instance) => {
+ cx.predefine_fn(instance, linkage, visibility, &symbol_name);
+ }
+ MonoItem::GlobalAsm(..) => {}
+ }
+
+ debug!(
+ "END PREDEFINING '{} ({})' in cgu {}",
+ self,
+ self.to_raw_string(),
+ cx.codegen_unit().name()
+ );
+ }
+
+ fn to_raw_string(&self) -> String {
+ match *self {
+ MonoItem::Fn(instance) => {
+ format!("Fn({:?}, {})", instance.def, instance.substs.as_ptr().addr())
+ }
+ MonoItem::Static(id) => format!("Static({:?})", id),
+ MonoItem::GlobalAsm(id) => format!("GlobalAsm({:?})", id),
+ }
+ }
+}