Add support for const operands and options to global_asm!
On x86, the default syntax is also switched to Intel to match asm!
This commit is contained in:
parent
952c5732c2
commit
5918ee4317
36 changed files with 928 additions and 800 deletions
|
@ -4,7 +4,8 @@ use rustc_errors::struct_span_err;
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -194,3 +195,32 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
|
||||
struct_span_err!(a, b, E0511, "{}", c).emit();
|
||||
}
|
||||
|
||||
pub fn asm_const_to_str<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sp: Span,
|
||||
const_value: ConstValue<'tcx>,
|
||||
ty_and_layout: TyAndLayout<'tcx>,
|
||||
) -> String {
|
||||
let scalar = match const_value {
|
||||
ConstValue::Scalar(s) => s,
|
||||
_ => {
|
||||
span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
|
||||
}
|
||||
};
|
||||
let value = scalar.assert_bits(ty_and_layout.size);
|
||||
match ty_and_layout.ty.kind() {
|
||||
ty::Uint(_) => value.to_string(),
|
||||
ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
|
||||
ty::IntTy::I8 => (value as i8).to_string(),
|
||||
ty::IntTy::I16 => (value as i16).to_string(),
|
||||
ty::IntTy::I32 => (value as i32).to_string(),
|
||||
ty::IntTy::I64 => (value as i64).to_string(),
|
||||
ty::IntTy::I128 => (value as i128).to_string(),
|
||||
ty::IntTy::Isize => unreachable!(),
|
||||
},
|
||||
ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(),
|
||||
ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(),
|
||||
_ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ use crate::MemFlags;
|
|||
use rustc_ast as ast;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::mir::AssertKind;
|
||||
use rustc_middle::mir::{self, SwitchTargets};
|
||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
||||
|
@ -825,33 +824,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let const_value = self
|
||||
.eval_mir_constant(value)
|
||||
.unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved"));
|
||||
let ty = value.ty();
|
||||
let size = bx.layout_of(ty).size;
|
||||
let scalar = match const_value {
|
||||
ConstValue::Scalar(s) => s,
|
||||
_ => span_bug!(
|
||||
span,
|
||||
"expected Scalar for promoted asm const, but got {:#?}",
|
||||
const_value
|
||||
),
|
||||
};
|
||||
let value = scalar.assert_bits(size);
|
||||
let string = match ty.kind() {
|
||||
ty::Uint(_) => value.to_string(),
|
||||
ty::Int(int_ty) => {
|
||||
match int_ty.normalize(bx.tcx().sess.target.pointer_width) {
|
||||
ty::IntTy::I8 => (value as i8).to_string(),
|
||||
ty::IntTy::I16 => (value as i16).to_string(),
|
||||
ty::IntTy::I32 => (value as i32).to_string(),
|
||||
ty::IntTy::I64 => (value as i64).to_string(),
|
||||
ty::IntTy::I128 => (value as i128).to_string(),
|
||||
ty::IntTy::Isize => unreachable!(),
|
||||
}
|
||||
}
|
||||
ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(),
|
||||
ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(),
|
||||
_ => span_bug!(span, "asm const has bad type {}", ty),
|
||||
};
|
||||
let string = common::asm_const_to_str(
|
||||
bx.tcx(),
|
||||
span,
|
||||
const_value,
|
||||
bx.layout_of(value.ty()),
|
||||
);
|
||||
InlineAsmOperandRef::Const { string }
|
||||
}
|
||||
mir::InlineAsmOperand::SymFn { ref value } => {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
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::layout::HasTyCtxt;
|
||||
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_target::abi::LayoutOf;
|
||||
|
||||
pub trait MonoItemExt<'a, 'tcx> {
|
||||
fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
|
||||
|
@ -32,8 +33,35 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
|||
}
|
||||
MonoItem::GlobalAsm(item_id) => {
|
||||
let item = cx.tcx().hir().item(item_id);
|
||||
if let hir::ItemKind::GlobalAsm(ref ga) = item.kind {
|
||||
cx.codegen_global_asm(ga);
|
||||
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 }
|
||||
}
|
||||
_ => 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")
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::mir::operand::OperandRef;
|
|||
use crate::mir::place::PlaceRef;
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{GlobalAsm, LlvmInlineAsmInner};
|
||||
use rustc_hir::LlvmInlineAsmInner;
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||
|
@ -36,6 +36,11 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GlobalAsmOperandRef {
|
||||
Const { string: String },
|
||||
}
|
||||
|
||||
pub trait AsmBuilderMethods<'tcx>: BackendTypes {
|
||||
/// Take an inline assembly expression and splat it out via LLVM
|
||||
fn codegen_llvm_inline_asm(
|
||||
|
@ -57,5 +62,11 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
|
|||
}
|
||||
|
||||
pub trait AsmMethods {
|
||||
fn codegen_global_asm(&self, ga: &GlobalAsm);
|
||||
fn codegen_global_asm(
|
||||
&self,
|
||||
template: &[InlineAsmTemplatePiece],
|
||||
operands: &[GlobalAsmOperandRef],
|
||||
options: InlineAsmOptions,
|
||||
line_spans: &[Span],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ mod type_;
|
|||
mod write;
|
||||
|
||||
pub use self::abi::AbiBuilderMethods;
|
||||
pub use self::asm::{AsmBuilderMethods, AsmMethods, InlineAsmOperandRef};
|
||||
pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
|
||||
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
|
||||
pub use self::builder::{BuilderMethods, OverflowOp};
|
||||
pub use self::consts::ConstMethods;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue