about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-05-13 22:17:43 +0000
committerbors <bors@rust-lang.org>2021-05-13 22:17:43 +0000
commit17f30e5451f581d753899d2f628e5be354df33cd (patch)
tree58252137260855f9c5791b84bda1dcdb4d90407b /compiler/rustc_codegen_ssa/src
parent6d395a1c2946c79966490f5b1e6e619d3a713e6b (diff)
parenta7ed6a5196996f00dd78a391a44af51ee8088058 (diff)
downloadrust-17f30e5451f581d753899d2f628e5be354df33cd.tar.gz
rust-17f30e5451f581d753899d2f628e5be354df33cd.zip
Auto merge of #84107 - Amanieu:global_asm2, r=nagisa
Add support for const operands and options to global_asm!

On x86, the default syntax is also switched to Intel to match asm!.

Currently `global_asm!` only supports `const` operands and the `att_syntax` option. In the future, `sym` operands will also be supported. However there is no plan to support any of the other operand types or options since they don't make sense in the context of `global_asm!`.

r? `@nagisa`
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs32
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs34
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/asm.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/mod.rs2
5 files changed, 83 insertions, 36 deletions
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index afd83bfcb56..955f658eb1c 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -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),
+    }
+}
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 72e9163b88e..2bd35fe9b14 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -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 } => {
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 8e79193759e..48d753e0d84 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -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")
                 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs
index 69931935c49..86f2781a766 100644
--- a/compiler/rustc_codegen_ssa/src/traits/asm.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs
@@ -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],
+    );
 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs
index be2e0ea230f..c529fbbf518 100644
--- a/compiler/rustc_codegen_ssa/src/traits/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs
@@ -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;