Skip to content

Commit

Permalink
Share part of the global_asm!() implementation between cg_ssa and cg_…
Browse files Browse the repository at this point in the history
…clif
  • Loading branch information
bjorn3 committed Jan 24, 2025
1 parent 3e61e7f commit 0b43964
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 135 deletions.
5 changes: 4 additions & 1 deletion compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,10 @@ fn codegen_cgu_content(
}
}
MonoItem::GlobalAsm(item_id) => {
crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id);
rustc_codegen_ssa::base::codegen_global_asm(
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
item_id,
);
}
}
}
Expand Down
62 changes: 0 additions & 62 deletions compiler/rustc_codegen_cranelift/src/global_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use std::sync::Arc;

use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::traits::{AsmCodegenMethods, GlobalAsmOperandRef};
use rustc_hir::{InlineAsmOperand, ItemId};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
Expand Down Expand Up @@ -91,66 +89,6 @@ impl<'tcx> HasTypingEnv<'tcx> for GlobalAsmContext<'_, 'tcx> {
}
}

pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
let item = tcx.hir().item(item_id);
let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind else {
bug!("Expected GlobalAsm found {:?}", item);
};

// Adapted from rustc_codegen_ssa::mono_items::MonoItem::define
let operands: Vec<_> = asm
.operands
.iter()
.map(|(op, op_sp)| match *op {
InlineAsmOperand::Const { ref anon_const } => {
match tcx.const_eval_poly(anon_const.def_id.to_def_id()) {
Ok(const_value) => {
let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
let string = rustc_codegen_ssa::common::asm_const_to_str(
tcx,
*op_sp,
const_value,
FullyMonomorphizedLayoutCx(tcx).layout_of(ty),
);
GlobalAsmOperandRef::Const { string }
}
Err(ErrorHandled::Reported { .. }) => {
// An error has already been reported and
// compilation is guaranteed to fail if execution
// hits this path. So an empty string instead of
// a stringified constant value will suffice.
GlobalAsmOperandRef::Const { string: String::new() }
}
Err(ErrorHandled::TooGeneric(_)) => {
span_bug!(*op_sp, "asm const cannot be resolved; too generic")
}
}
}
InlineAsmOperand::SymFn { ref anon_const } => {
let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
let instance = match ty.kind() {
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
_ => span_bug!(*op_sp, "asm sym is not a function"),
};

GlobalAsmOperandRef::SymFn { instance }
}
InlineAsmOperand::SymStatic { path: _, def_id } => {
GlobalAsmOperandRef::SymStatic { def_id }
}
InlineAsmOperand::In { .. }
| InlineAsmOperand::Out { .. }
| InlineAsmOperand::InOut { .. }
| InlineAsmOperand::SplitInOut { .. }
| InlineAsmOperand::Label { .. } => {
span_bug!(*op_sp, "invalid operand type for global_asm!")
}
})
.collect();

codegen_global_asm_inner(tcx, global_asm, asm.template, &operands, asm.options, asm.line_spans);
}

fn codegen_global_asm_inner<'tcx>(
tcx: TyCtxt<'tcx>,
global_asm: &mut String,
Expand Down
67 changes: 66 additions & 1 deletion compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_data_structures::sync::{Lrc, par_map};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::ItemId;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_metadata::EncodedMetadata;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_middle::middle::{exported_symbols, lang_items};
use rustc_middle::mir::BinOp;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
use rustc_span::{DUMMY_SP, Symbol, sym};
Expand Down Expand Up @@ -420,6 +422,69 @@ pub(crate) fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
mir::codegen_mir::<Bx>(cx, instance);
}

pub fn codegen_global_asm<'tcx, Cx>(cx: &mut Cx, item_id: ItemId)
where
Cx: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + AsmCodegenMethods<'tcx>,
{
let item = cx.tcx().hir().item(item_id);
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
let operands: Vec<_> = asm
.operands
.iter()
.map(|(op, op_sp)| match *op {
rustc_hir::InlineAsmOperand::Const { ref anon_const } => {
match cx.tcx().const_eval_poly(anon_const.def_id.to_def_id()) {
Ok(const_value) => {
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 }
}
Err(ErrorHandled::Reported { .. }) => {
// An error has already been reported and
// compilation is guaranteed to fail if execution
// hits this path. So an empty string instead of
// a stringified constant value will suffice.
GlobalAsmOperandRef::Const { string: String::new() }
}
Err(ErrorHandled::TooGeneric(_)) => {
span_bug!(*op_sp, "asm const cannot be resolved; too generic")
}
}
}
rustc_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, args) => Instance::new(def_id, args),
_ => span_bug!(*op_sp, "asm sym is not a function"),
};

GlobalAsmOperandRef::SymFn { instance }
}
rustc_hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
GlobalAsmOperandRef::SymStatic { def_id }
}
rustc_hir::InlineAsmOperand::In { .. }
| rustc_hir::InlineAsmOperand::Out { .. }
| rustc_hir::InlineAsmOperand::InOut { .. }
| rustc_hir::InlineAsmOperand::SplitInOut { .. }
| rustc_hir::InlineAsmOperand::Label { .. } => {
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")
}
}

/// Creates the `main` function which will initialize the rust runtime and call
/// users main function.
pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
Expand Down
74 changes: 3 additions & 71 deletions compiler/rustc_codegen_ssa/src/mono_item.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
use rustc_hir as hir;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
use rustc_middle::ty::Instance;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::{span_bug, ty};
use rustc_middle::ty::layout::HasTyCtxt;
use tracing::debug;

use crate::base;
use crate::mir::naked_asm;
use crate::traits::*;
use crate::{base, common};

pub trait MonoItemExt<'a, 'tcx> {
fn define<Bx: BuilderMethods<'a, 'tcx>>(
Expand Down Expand Up @@ -44,71 +40,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
cx.codegen_static(def_id);
}
MonoItem::GlobalAsm(item_id) => {
let item = cx.tcx().hir().item(item_id);
if let hir::ItemKind::GlobalAsm(asm) = item.kind {
let operands: Vec<_> = asm
.operands
.iter()
.map(|(op, op_sp)| match *op {
hir::InlineAsmOperand::Const { ref anon_const } => {
match cx.tcx().const_eval_poly(anon_const.def_id.to_def_id()) {
Ok(const_value) => {
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 }
}
Err(ErrorHandled::Reported { .. }) => {
// An error has already been reported and
// compilation is guaranteed to fail if execution
// hits this path. So an empty string instead of
// a stringified constant value will suffice.
GlobalAsmOperandRef::Const { string: String::new() }
}
Err(ErrorHandled::TooGeneric(_)) => {
span_bug!(
*op_sp,
"asm const cannot be resolved; too generic"
)
}
}
}
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, args) => Instance::new(def_id, args),
_ => 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 { .. }
| hir::InlineAsmOperand::Label { .. } => {
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")
}
base::codegen_global_asm(cx, item_id);
}
MonoItem::Fn(instance) => {
if cx
Expand Down

0 comments on commit 0b43964

Please sign in to comment.