From 4d57548cdd4be2e66418314bb084936e8adb1788 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Wed, 23 Oct 2024 03:33:56 +0800 Subject: [PATCH] wip --- compiler/rustc_codegen_gcc/src/asm.rs | 23 +++++--- compiler/rustc_codegen_llvm/src/asm.rs | 18 +++++- compiler/rustc_codegen_ssa/src/common.rs | 59 ++++++++++++++----- compiler/rustc_codegen_ssa/src/mir/block.rs | 36 ++++++----- compiler/rustc_codegen_ssa/src/mono_item.rs | 17 ++++-- compiler/rustc_codegen_ssa/src/traits/asm.rs | 4 +- .../src/check/intrinsicck.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 1 + 8 files changed, 115 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index a04cd4735f478..e25610e6050a0 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -5,8 +5,7 @@ use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::operand::OperandValue; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ - AsmBuilderMethods, AsmCodegenMethods, BaseTypeCodegenMethods, BuilderMethods, - GlobalAsmOperandRef, InlineAsmOperandRef, + AsmBuilderMethods, AsmCodegenMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, GlobalAsmOperandRef, InlineAsmOperandRef }; use rustc_middle::bug; use rustc_middle::ty::Instance; @@ -282,7 +281,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // or byte count suffixes (x86 Windows). constants_len += self.tcx.symbol_name(instance).name.len(); } - InlineAsmOperandRef::SymStatic { def_id } => { + InlineAsmOperandRef::SymStatic { def_id, offset } => { // TODO(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O). constants_len += @@ -379,11 +378,18 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { }); } - InlineAsmOperandRef::SymStatic { def_id } => { + InlineAsmOperandRef::SymStatic { def_id, offset } => { + let val = self.cx.get_static(def_id).get_address(None); + let val = if offset.bytes() > 0 { + let offset = self.cx.const_int(self.int_type, offset.bytes().try_into().expect("offset is out of range")); + val + offset + } else { + val + }; inputs.push(AsmInOperand { constraint: "X".into(), rust_idx, - val: self.cx.get_static(def_id).get_address(None), + val, }); } @@ -472,7 +478,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { template_str.push_str(name); } - InlineAsmOperandRef::SymStatic { def_id } => { + InlineAsmOperandRef::SymStatic { def_id, offset } => { // TODO(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O). let instance = Instance::mono(self.tcx, def_id); @@ -833,10 +839,13 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { template_str.push_str(name); } - GlobalAsmOperandRef::SymStatic { def_id } => { + GlobalAsmOperandRef::SymStatic { def_id, offset } => { // TODO(antoyo): set the global variable as used. // TODO(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O). + if offset.bytes() > 0 { + bug!("We don't know how to handle statics with non-zero offset") + } let instance = Instance::mono(self.tcx, def_id); let name = self.tcx.symbol_name(instance).name; template_str.push_str(name); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index d1d7d0cf4ce4d..4429e7d77c7bc 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -164,8 +164,15 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { op_idx.insert(idx, constraints.len()); constraints.push("s".to_string()); } - InlineAsmOperandRef::SymStatic { def_id } => { - inputs.push(self.cx.get_static(def_id)); + InlineAsmOperandRef::SymStatic { def_id, offset } => { + let llval = self.cx.get_static(def_id); + let llval = if offset.bytes() > 0 { + let offset = self.const_usize(offset.bytes()); + self.ptradd(llval, offset) + } else { + llval + }; + inputs.push(llval); op_idx.insert(idx, constraints.len()); constraints.push("s".to_string()); } @@ -395,7 +402,12 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { .expect("symbol is not valid UTF-8"); template_str.push_str(&symbol); } - GlobalAsmOperandRef::SymStatic { def_id } => { + GlobalAsmOperandRef::SymStatic { def_id, offset } => { + if offset.bytes() > 0 { + bug!( + "We don't know how to codegen on static with a non-zero offset" + ); + } let llval = self .renamed_statics .borrow() diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 582a2a87e4867..791b68d2f7a59 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -1,6 +1,8 @@ #![allow(non_camel_case_types)] +use rustc_abi::Size; use rustc_hir::LangItem; +use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_middle::{bug, mir, span_bug}; @@ -155,27 +157,56 @@ pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -pub fn asm_const_to_str<'tcx>( +pub enum AsmConstOperandRef { + Const { string: String }, + Static { def_id: DefId, offset: Size, ptr_size: u8 }, +} + +pub fn asm_const_to_opr_ref<'tcx>( tcx: TyCtxt<'tcx>, sp: Span, const_value: mir::ConstValue<'tcx>, ty_and_layout: TyAndLayout<'tcx>, -) -> String { +) -> AsmConstOperandRef { let mir::ConstValue::Scalar(scalar) = const_value else { span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value) }; - let value = scalar.assert_scalar_int().to_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!(), - }, - _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty), + match scalar.try_to_scalar_int() { + Ok(value) => { + let value = value.to_bits(ty_and_layout.size); + AsmConstOperandRef::Const { + string: 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!(), + }, + _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty), + }, + } + } + Err(mir::interpret::Scalar::Ptr(ptr, sz)) => { + let (alloc, offset) = ptr.into_parts(); + match tcx.global_alloc(alloc) { + mir::interpret::GlobalAlloc::Memory(alloc) => { + span_bug!(sp, "unexpected memory for `{alloc:?}` for a const operand") + } + mir::interpret::GlobalAlloc::Function { instance } => { + span_bug!(sp, "unexpected function for `{instance}` for a const operand") + } + mir::interpret::GlobalAlloc::VTable(ty, _) => { + span_bug!(sp, "unexpected vtable for `{ty}` for a const operand") + } + mir::interpret::GlobalAlloc::Static(def_id) => { + AsmConstOperandRef::Static { def_id, offset, ptr_size: sz } + } + } + } + Err(scalar) => span_bug!(sp, "unexpected `{:#?}` for a const operand", scalar), } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index e3553dc03e106..bfb17941f34d6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1,5 +1,6 @@ use std::cmp; +use rustc_abi::Size; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; @@ -1167,31 +1168,36 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::InlineAsmOperand::Const { ref value } => { let const_value = self.eval_mir_constant(value); - let string = common::asm_const_to_str( + match common::asm_const_to_opr_ref( bx.tcx(), span, const_value, bx.layout_of(value.ty()), - ); - InlineAsmOperandRef::Const { string } + ) { + common::AsmConstOperandRef::Const { string } => { + InlineAsmOperandRef::Const { string } + } + common::AsmConstOperandRef::Static { def_id, offset, ptr_size: _ } => { + InlineAsmOperandRef::SymStatic { def_id, offset } + } + } } mir::InlineAsmOperand::SymFn { ref value } => { let const_ = self.monomorphize(value.const_); - if let ty::FnDef(def_id, args) = *const_.ty().kind() { - let instance = ty::Instance::resolve_for_fn_ptr( - bx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - args, - ) - .unwrap(); - InlineAsmOperandRef::SymFn { instance } - } else { + let ty::FnDef(def_id, args) = *const_.ty().kind() else { span_bug!(span, "invalid type for asm sym (fn)"); - } + }; + let instance = ty::Instance::resolve_for_fn_ptr( + bx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + args, + ) + .unwrap(); + InlineAsmOperandRef::SymFn { instance } } mir::InlineAsmOperand::SymStatic { def_id } => { - InlineAsmOperandRef::SymStatic { def_id } + InlineAsmOperandRef::SymStatic { def_id, offset: Size::ZERO } } mir::InlineAsmOperand::Label { target_index } => { InlineAsmOperandRef::Label { label: self.llbb(targets[target_index]) } diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 038c5857face1..8eebb3fed4413 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -1,3 +1,4 @@ +use rustc_abi::Size; use rustc_hir as hir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; @@ -47,13 +48,21 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { .tcx() .typeck_body(anon_const.body) .node_type(anon_const.hir_id); - let string = common::asm_const_to_str( + match common::asm_const_to_opr_ref( cx.tcx(), *op_sp, const_value, cx.layout_of(ty), - ); - GlobalAsmOperandRef::Const { string } + ) { + common::AsmConstOperandRef::Const { string } => { + GlobalAsmOperandRef::Const { string } + } + common::AsmConstOperandRef::Static { + def_id, + offset, + ptr_size: _, + } => GlobalAsmOperandRef::SymStatic { def_id, offset }, + } } Err(ErrorHandled::Reported { .. }) => { // An error has already been reported and @@ -83,7 +92,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { GlobalAsmOperandRef::SymFn { instance } } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { - GlobalAsmOperandRef::SymStatic { def_id } + GlobalAsmOperandRef::SymStatic { def_id, offset: Size::ZERO } } hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Out { .. } diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index f4853da115648..b8c170a52313c 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -1,3 +1,4 @@ +use rustc_abi::Size; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::def_id::DefId; use rustc_middle::ty::Instance; @@ -33,6 +34,7 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { }, SymStatic { def_id: DefId, + offset: Size, }, Label { label: B::BasicBlock, @@ -43,7 +45,7 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { pub enum GlobalAsmOperandRef<'tcx> { Const { string: String }, SymFn { instance: Instance<'tcx> }, - SymStatic { def_id: DefId }, + SymStatic { def_id: DefId, offset: Size }, } pub trait AsmBuilderMethods<'tcx>: BackendTypes { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index bbff00cd3b3c2..16360d2f26f19 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -459,7 +459,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { hir::InlineAsmOperand::Const { anon_const } => { debug_assert_matches!( self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), - ty::Error(_) | ty::Int(_) | ty::Uint(_) + ty::Error(_) | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) ); } // Typeck has checked that SymFn refers to a function. diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 470bcaeded167..e2e47cbb6d9af 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -91,6 +91,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { match ty.kind() { ty::Error(_) => ty, ty::Int(_) | ty::Uint(_) => ty, + ty::RawPtr(..) => ty, _ => { let guar = tcx .dcx()