From 49ae3b7867a09fefee26f1ff34890f7a3e230f28 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 15 Jul 2023 12:38:59 +0000 Subject: Extract a create_wrapper_function for use in allocator shim writing This deduplicates some logic and makes it easier to follow what wrappers are produced. In the future it may allow moving the code to determine which wrappers to create to cg_ssa. --- compiler/rustc_codegen_llvm/src/allocator.rs | 182 +++++++++++++-------------- 1 file changed, 90 insertions(+), 92 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index ca123334fca..48d4a9cf803 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::config::{DebugInfo, OomStrategy}; use crate::debuginfo; -use crate::llvm::{self, False, True}; +use crate::llvm::{self, Context, False, Module, True, Type}; use crate::ModuleLlvm; pub(crate) unsafe fn codegen( @@ -29,7 +29,6 @@ pub(crate) unsafe fn codegen( }; let i8 = llvm::LLVMInt8TypeInContext(llcx); let i8p = llvm::LLVMPointerTypeInContext(llcx, 0); - let void = llvm::LLVMVoidTypeInContext(llcx); if kind == AllocatorKind::Default { for method in ALLOCATOR_METHODS { @@ -54,102 +53,25 @@ pub(crate) unsafe fn codegen( panic!("invalid allocator output") } }; - let ty = llvm::LLVMFunctionType( - output.unwrap_or(void), - args.as_ptr(), - args.len() as c_uint, - False, - ); - let name = global_fn_name(method.name); - let llfn = - llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty); - - if tcx.sess.target.default_hidden_visibility { - llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); - } - if tcx.sess.must_emit_unwind_tables() { - let uwtable = attributes::uwtable_attr(llcx); - attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]); - } - let callee = default_fn_name(method.name); - let callee = - llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); - llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); - - let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); - - let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); - llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); - let args = args - .iter() - .enumerate() - .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint)) - .collect::>(); - let ret = llvm::LLVMRustBuildCall( - llbuilder, - ty, - callee, - args.as_ptr(), - args.len() as c_uint, - [].as_ptr(), - 0 as c_uint, - ); - llvm::LLVMSetTailCall(ret, True); - if output.is_some() { - llvm::LLVMBuildRet(llbuilder, ret); - } else { - llvm::LLVMBuildRetVoid(llbuilder); - } - llvm::LLVMDisposeBuilder(llbuilder); + let from_name = global_fn_name(method.name); + let to_name = default_fn_name(method.name); + + create_wrapper_function(tcx, llcx, llmod, &from_name, &to_name, &args, output, false); } } // rust alloc error handler - let args = [usize, usize]; // size, align - - let ty = llvm::LLVMFunctionType(void, args.as_ptr(), args.len() as c_uint, False); - let name = "__rust_alloc_error_handler"; - let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty); - // -> ! DIFlagNoReturn - let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx); - attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]); - - if tcx.sess.target.default_hidden_visibility { - llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); - } - if tcx.sess.must_emit_unwind_tables() { - let uwtable = attributes::uwtable_attr(llcx); - attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]); - } - - let callee = alloc_error_handler_name(alloc_error_handler_kind); - let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); - // -> ! DIFlagNoReturn - attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); - llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); - - let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); - - let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); - llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); - let args = args - .iter() - .enumerate() - .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint)) - .collect::>(); - let ret = llvm::LLVMRustBuildCall( - llbuilder, - ty, - callee, - args.as_ptr(), - args.len() as c_uint, - [].as_ptr(), - 0 as c_uint, + create_wrapper_function( + tcx, + llcx, + llmod, + "__rust_alloc_error_handler", + &alloc_error_handler_name(alloc_error_handler_kind), + &[usize, usize], // size, align + None, + true, ); - llvm::LLVMSetTailCall(ret, True); - llvm::LLVMBuildRetVoid(llbuilder); - llvm::LLVMDisposeBuilder(llbuilder); // __rust_alloc_error_handler_should_panic let name = OomStrategy::SYMBOL; @@ -175,3 +97,79 @@ pub(crate) unsafe fn codegen( dbg_cx.finalize(tcx.sess); } } + +fn create_wrapper_function( + tcx: TyCtxt<'_>, + llcx: &Context, + llmod: &Module, + from_name: &str, + to_name: &str, + args: &[&Type], + output: Option<&Type>, + no_return: bool, +) { + unsafe { + let ty = llvm::LLVMFunctionType( + output.unwrap_or_else(|| llvm::LLVMVoidTypeInContext(llcx)), + args.as_ptr(), + args.len() as c_uint, + False, + ); + let llfn = llvm::LLVMRustGetOrInsertFunction( + llmod, + from_name.as_ptr().cast(), + from_name.len(), + ty, + ); + let no_return = if no_return { + // -> ! DIFlagNoReturn + let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx); + attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]); + Some(no_return) + } else { + None + }; + + if tcx.sess.target.default_hidden_visibility { + llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); + } + if tcx.sess.must_emit_unwind_tables() { + let uwtable = attributes::uwtable_attr(llcx); + attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]); + } + + let callee = + llvm::LLVMRustGetOrInsertFunction(llmod, to_name.as_ptr().cast(), to_name.len(), ty); + if let Some(no_return) = no_return { + // -> ! DIFlagNoReturn + attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); + } + llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); + + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); + + let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); + llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); + let args = args + .iter() + .enumerate() + .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint)) + .collect::>(); + let ret = llvm::LLVMRustBuildCall( + llbuilder, + ty, + callee, + args.as_ptr(), + args.len() as c_uint, + [].as_ptr(), + 0 as c_uint, + ); + llvm::LLVMSetTailCall(ret, True); + if output.is_some() { + llvm::LLVMBuildRet(llbuilder, ret); + } else { + llvm::LLVMBuildRetVoid(llbuilder); + } + llvm::LLVMDisposeBuilder(llbuilder); + } +} -- cgit 1.4.1-3-g733a5 From a3ab31c0f957998cc16e1760e965c85a4923950b Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 4 Aug 2023 16:09:54 +0100 Subject: Use `unstable_target_features` when checking inline assembly This is necessary to properly validate register classes even when the relevant target feature name is still unstable. --- compiler/rustc_codegen_gcc/src/asm.rs | 4 ++-- compiler/rustc_codegen_llvm/src/asm.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 4c3b7f5036c..73908558cee 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -107,7 +107,7 @@ enum ConstraintOrRegister { impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { if options.contains(InlineAsmOptions::MAY_UNWIND) { self.sess() .create_err(UnwindingInlineAsm { span: span[0] }) @@ -173,7 +173,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let is_target_supported = reg.reg_class().supported_types(asm_arch).iter() .any(|&(_, feature)| { if let Some(feature) = feature { - self.tcx.sess.target_features.contains(&feature) + self.tcx.asm_target_features(instance.def_id()).contains(&feature) } else { true // Register class is unconditionally supported } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 2a6ad1be763..f5284395042 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -44,9 +44,10 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let is_target_supported = |reg_class: InlineAsmRegClass| { for &(_, feature) in reg_class.supported_types(asm_arch) { if let Some(feature) = feature { - let codegen_fn_attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - if self.tcx.sess.target_features.contains(&feature) - || codegen_fn_attrs.target_features.contains(&feature) + if self + .tcx + .asm_target_features(instance.def_id()) + .contains(&feature) { return true; } -- cgit 1.4.1-3-g733a5 From d16409fe228f07c8a702ace7b42c1e1196ff85e6 Mon Sep 17 00:00:00 2001 From: Dirreke Date: Thu, 13 Jul 2023 22:19:59 +0800 Subject: add a csky-unknown-linux-gnuabiv2 target --- compiler/rustc_codegen_gcc/example/alloc_system.rs | 1 + compiler/rustc_codegen_gcc/src/asm.rs | 5 + compiler/rustc_codegen_llvm/src/asm.rs | 6 + compiler/rustc_llvm/build.rs | 1 + compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 7 + compiler/rustc_llvm/src/lib.rs | 8 ++ compiler/rustc_target/src/abi/call/csky.rs | 31 +++++ compiler/rustc_target/src/abi/call/mod.rs | 2 + compiler/rustc_target/src/asm/csky.rs | 142 +++++++++++++++++++++ compiler/rustc_target/src/asm/mod.rs | 24 ++++ .../src/spec/csky_unknown_linux_gnuabiv2.rs | 22 ++++ compiler/rustc_target/src/spec/mod.rs | 1 + config.example.toml | 2 +- library/core/src/ffi/mod.rs | 3 +- library/std/src/env.rs | 1 + library/std/src/os/l4re/raw.rs | 1 + library/std/src/os/linux/raw.rs | 1 + library/std/src/sys/common/alloc.rs | 1 + library/std/src/sys/personality/gcc.rs | 3 + library/unwind/src/libunwind.rs | 3 + src/bootstrap/bootstrap.py | 1 + src/bootstrap/lib.rs | 2 +- src/bootstrap/llvm.rs | 2 +- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../csky-unknown-linux-gnuabiv2.md | 33 +++++ .../src/language-features/asm-experimental-arch.md | 9 ++ src/librustdoc/clean/cfg.rs | 1 + src/tools/build-manifest/src/main.rs | 1 + .../src/completions/attribute/cfg.rs | 1 + 30 files changed, 313 insertions(+), 4 deletions(-) create mode 100644 compiler/rustc_target/src/abi/call/csky.rs create mode 100644 compiler/rustc_target/src/asm/csky.rs create mode 100644 compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs create mode 100644 src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs index e756b347e89..3deef419f42 100644 --- a/compiler/rustc_codegen_gcc/example/alloc_system.rs +++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs @@ -12,6 +12,7 @@ target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", + target_arch = "csky" target_arch = "powerpc64"))] const MIN_ALIGN: usize = 8; #[cfg(any(target_arch = "x86_64", diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 4c3b7f5036c..0482a85f5f3 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -597,6 +597,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", @@ -673,6 +675,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Msp430(_) => unimplemented!(), @@ -860,6 +864,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option InlineAsmRegClass::S390x(_) => None, InlineAsmRegClass::Msp430(_) => None, InlineAsmRegClass::M68k(_) => None, + InlineAsmRegClass::CSKY(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 2a6ad1be763..4d7db96cc82 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -261,6 +261,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { InlineAsmArch::M68k => { constraints.push("~{ccr}".to_string()); } + InlineAsmArch::CSKY => {} // https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h getClobers() } } if !options.contains(InlineAsmOptions::NOMEM) { @@ -693,6 +694,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } @@ -792,6 +795,7 @@ fn modifier_to_llvm( bug!("LLVM backend does not support SPIR-V") } InlineAsmRegClass::M68k(_) => None, + InlineAsmRegClass::CSKY(_) => None, InlineAsmRegClass::Err => unreachable!(), } } @@ -868,6 +872,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index aa1121d6bb3..4302b161833 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -12,6 +12,7 @@ const OPTIONAL_COMPONENTS: &[&str] = &[ "avr", "loongarch", "m68k", + "csky", "mips", "powerpc", "systemz", diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index b3371dbe834..b566ea496de 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -105,6 +105,12 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { #define SUBTARGET_M68K #endif +#ifdef LLVM_COMPONENT_CSKY +#define SUBTARGET_CSKY SUBTARGET(CSKY) +#else +#define SUBTARGET_CSKY +#endif + #ifdef LLVM_COMPONENT_MIPS #define SUBTARGET_MIPS SUBTARGET(Mips) #else @@ -159,6 +165,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { SUBTARGET_AARCH64 \ SUBTARGET_AVR \ SUBTARGET_M68K \ + SUBTARGET_CSKY \ SUBTARGET_MIPS \ SUBTARGET_PPC \ SUBTARGET_SYSTEMZ \ diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index a49ded4fd7b..eb70961503d 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -102,6 +102,14 @@ pub fn initialize_available_targets() { LLVMInitializeM68kAsmPrinter, LLVMInitializeM68kAsmParser ); + init_target!( + llvm_component = "csky", + LLVMInitializeCSKYTargetInfo, + LLVMInitializeCSKYTarget, + LLVMInitializeCSKYTargetMC, + LLVMInitializeCSKYAsmPrinter, + LLVMInitializeCSKYAsmParser + ); init_target!( llvm_component = "loongarch", LLVMInitializeLoongArchTargetInfo, diff --git a/compiler/rustc_target/src/abi/call/csky.rs b/compiler/rustc_target/src/abi/call/csky.rs new file mode 100644 index 00000000000..75b453daa4f --- /dev/null +++ b/compiler/rustc_target/src/abi/call/csky.rs @@ -0,0 +1,31 @@ +//see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/CSKY/CSKYCallingConv.td +use crate::abi::call::{ArgAbi, FnAbi}; + +fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { + if ret.layout.is_aggregate() || ret.layout.size.bits() > 64 { + ret.make_indirect(); + } else { + ret.extend_integer_width_to(32); + } +} + +fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { + if arg.layout.is_aggregate() || arg.layout.size.bits() > 64 { + arg.make_indirect(); + } else { + arg.extend_integer_width_to(32); + } +} + +pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in fn_abi.args.iter_mut() { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } +} diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index e4989bdfbcd..8fab13d5d5d 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -9,6 +9,7 @@ mod amdgpu; mod arm; mod avr; mod bpf; +mod csky; mod hexagon; mod loongarch; mod m68k; @@ -712,6 +713,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "avr" => avr::compute_abi_info(self), "loongarch64" => loongarch::compute_abi_info(cx, self), "m68k" => m68k::compute_abi_info(self), + "csky" => csky::compute_abi_info(self), "mips" | "mips32r6" => mips::compute_abi_info(cx, self), "mips64" | "mips64r6" => mips64::compute_abi_info(cx, self), "powerpc" => powerpc::compute_abi_info(self), diff --git a/compiler/rustc_target/src/asm/csky.rs b/compiler/rustc_target/src/asm/csky.rs new file mode 100644 index 00000000000..13bb846c731 --- /dev/null +++ b/compiler/rustc_target/src/asm/csky.rs @@ -0,0 +1,142 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use rustc_span::Symbol; +use std::fmt; + +def_reg_class! { + CSKY CSKYInlineAsmRegClass { + reg, + freg, + } +} + +impl CSKYInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + _arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option)] { + match self { + Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, + Self::freg => types! { _: F32, F64; }, + } + } +} + +// The reserved registers are taken from +def_regs! { + CSKY CSKYInlineAsmReg CSKYInlineAsmRegClass { + r0: reg = ["r0","a0"], + r1: reg = ["r1","a1"], + r2: reg = ["r2","a2"], + r3: reg = ["r3","a3"], + r4: reg = ["r4","l0"], + r5: reg = ["r5","l1"], + r6: reg = ["r6","l2"], + // r7: reg = ["r7","l3"], + // r8: reg = ["r8","l4"], + // r9: reg = ["r9","l5"], + // r10: reg = ["r10","l6"], + // r11: reg = ["r11","l7"], + // r12: reg = ["r12","t0"], + // r13: reg = ["r13","t1"], + // r14: reg = ["r14","sp"], + // r15: reg = ["r15","lr"], + // r16: reg = ["r16","l8"], + // r17: reg = ["r17","l9"], + // r18: reg = ["r18","t2"], + // r19: reg = ["r19","t3"], + // r20: reg = ["r20","t4"], + // r21: reg = ["r21","t5"], + // r22: reg = ["r22","t6"], + // r23: reg = ["r23","t7", "fp"], + // r24: reg = ["r24","t8", "sop"], + // r25: reg = ["r25","tp", "bsp"], + // r26: reg = ["r26"], + // r27: reg = ["r27"], + // r28: reg = ["r28","gb", "rgb", "rdb"], + // r29: reg = ["r29","tb", "rtb"], + // r30: reg = ["r30","svbr"], + // r31: reg = ["r31","tls"], + f0: freg = ["fr0","vr0"], + f1: freg = ["fr1","vr1"], + f2: freg = ["fr2","vr2"], + f3: freg = ["fr3","vr3"], + f4: freg = ["fr4","vr4"], + f5: freg = ["fr5","vr5"], + f6: freg = ["fr6","vr6"], + f7: freg = ["fr7","vr7"], + f8: freg = ["fr8","vr8"], + f9: freg = ["fr9","vr9"], + f10: freg = ["fr10","vr10"], + f11: freg = ["fr11","vr11"], + f12: freg = ["fr12","vr12"], + f13: freg = ["fr13","vr13"], + f14: freg = ["fr14","vr14"], + f15: freg = ["fr15","vr15"], + f16: freg = ["fr16","vr16"], + f17: freg = ["fr17","vr17"], + f18: freg = ["fr18","vr18"], + f19: freg = ["fr19","vr19"], + f20: freg = ["fr20","vr20"], + f21: freg = ["fr21","vr21"], + f22: freg = ["fr22","vr22"], + f23: freg = ["fr23","vr23"], + f24: freg = ["fr24","vr24"], + f25: freg = ["fr25","vr25"], + f26: freg = ["fr26","vr26"], + f27: freg = ["fr27","vr27"], + f28: freg = ["fr28","vr28"], + f29: freg = ["fr29","vr29"], + f30: freg = ["fr30","vr30"], + f31: freg = ["fr31","vr31"], + #error = ["r7", "l3"] => + "the base pointer cannot be used as an operand for inline asm", + #error = ["r8","l4"] => + "the frame pointer cannot be used as an operand for inline asm", + #error = ["r14","sp"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["r15","lr"] => + "the link register cannot be used as an operand for inline asm", + #error = ["r31","tls"] => + "reserver for tls", + #error = ["r28", "gb", "rgb", "rdb"] => + "the global pointer cannot be used as an operand for inline asm", + #error = ["r9","l5", "r10","l6", "r11","l7", "r12","t0", "r13","t1"] => + "reserved (no E2)", + #error = ["r16","l8", "r17","l9", "r18","t2", "r19","t3", "r20","t4", "r21","t5", "r22","t6", "r23","t7", "fp", "r24","t8", "sop", "r25","tp", "bsp"] => + "reserved (no HighRegisters)", + #error = ["r26","r27","r29","tb", "rtb", "r30","svbr"] => + "reserved by the ABI", + } +} + +impl CSKYInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option, + ) -> fmt::Result { + out.write_str(self.name()) + } +} diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 7c27732079b..a11884bea26 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -167,6 +167,7 @@ mod aarch64; mod arm; mod avr; mod bpf; +mod csky; mod hexagon; mod loongarch; mod m68k; @@ -184,6 +185,7 @@ pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; +pub use csky::{CSKYInlineAsmReg, CSKYInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use loongarch::{LoongArchInlineAsmReg, LoongArchInlineAsmRegClass}; pub use m68k::{M68kInlineAsmReg, M68kInlineAsmRegClass}; @@ -220,6 +222,7 @@ pub enum InlineAsmArch { Avr, Msp430, M68k, + CSKY, } impl FromStr for InlineAsmArch { @@ -248,6 +251,7 @@ impl FromStr for InlineAsmArch { "avr" => Ok(Self::Avr), "msp430" => Ok(Self::Msp430), "m68k" => Ok(Self::M68k), + "csky" => Ok(Self::CSKY), _ => Err(()), } } @@ -272,6 +276,7 @@ pub enum InlineAsmReg { Avr(AvrInlineAsmReg), Msp430(Msp430InlineAsmReg), M68k(M68kInlineAsmReg), + CSKY(CSKYInlineAsmReg), // Placeholder for invalid register constraints for the current target Err, } @@ -292,6 +297,7 @@ impl InlineAsmReg { Self::Avr(r) => r.name(), Self::Msp430(r) => r.name(), Self::M68k(r) => r.name(), + Self::CSKY(r) => r.name(), Self::Err => "", } } @@ -311,6 +317,7 @@ impl InlineAsmReg { Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()), Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()), Self::M68k(r) => InlineAsmRegClass::M68k(r.reg_class()), + Self::CSKY(r) => InlineAsmRegClass::CSKY(r.reg_class()), Self::Err => InlineAsmRegClass::Err, } } @@ -344,6 +351,7 @@ impl InlineAsmReg { InlineAsmArch::Avr => Self::Avr(AvrInlineAsmReg::parse(name)?), InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(name)?), InlineAsmArch::M68k => Self::M68k(M68kInlineAsmReg::parse(name)?), + InlineAsmArch::CSKY => Self::CSKY(CSKYInlineAsmReg::parse(name)?), }) } @@ -371,6 +379,7 @@ impl InlineAsmReg { Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::M68k(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::CSKY(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Err => unreachable!(), } } @@ -397,6 +406,7 @@ impl InlineAsmReg { Self::Avr(r) => r.emit(out, arch, modifier), Self::Msp430(r) => r.emit(out, arch, modifier), Self::M68k(r) => r.emit(out, arch, modifier), + Self::CSKY(r) => r.emit(out, arch, modifier), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -416,6 +426,7 @@ impl InlineAsmReg { Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), Self::Msp430(_) => cb(self), Self::M68k(_) => cb(self), + Self::CSKY(_) => cb(self), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -440,6 +451,7 @@ pub enum InlineAsmRegClass { Avr(AvrInlineAsmRegClass), Msp430(Msp430InlineAsmRegClass), M68k(M68kInlineAsmRegClass), + CSKY(CSKYInlineAsmRegClass), // Placeholder for invalid register constraints for the current target Err, } @@ -463,6 +475,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.name(), Self::Msp430(r) => r.name(), Self::M68k(r) => r.name(), + Self::CSKY(r) => r.name(), Self::Err => rustc_span::symbol::sym::reg, } } @@ -488,6 +501,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Avr), Self::Msp430(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Msp430), Self::M68k(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::M68k), + Self::CSKY(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::CSKY), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -520,6 +534,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.suggest_modifier(arch, ty), Self::Msp430(r) => r.suggest_modifier(arch, ty), Self::M68k(r) => r.suggest_modifier(arch, ty), + Self::CSKY(r) => r.suggest_modifier(arch, ty), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -548,6 +563,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.default_modifier(arch), Self::Msp430(r) => r.default_modifier(arch), Self::M68k(r) => r.default_modifier(arch), + Self::CSKY(r) => r.default_modifier(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -575,6 +591,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.supported_types(arch), Self::Msp430(r) => r.supported_types(arch), Self::M68k(r) => r.supported_types(arch), + Self::CSKY(r) => r.supported_types(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -607,6 +624,7 @@ impl InlineAsmRegClass { InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(name)?), InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(name)?), InlineAsmArch::M68k => Self::M68k(M68kInlineAsmRegClass::parse(name)?), + InlineAsmArch::CSKY => Self::CSKY(CSKYInlineAsmRegClass::parse(name)?), }) } @@ -630,6 +648,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.valid_modifiers(arch), Self::Msp430(r) => r.valid_modifiers(arch), Self::M68k(r) => r.valid_modifiers(arch), + Self::CSKY(r) => r.valid_modifiers(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -826,6 +845,11 @@ pub fn allocatable_registers( m68k::fill_reg_map(arch, reloc_model, target_features, target, &mut map); map } + InlineAsmArch::CSKY => { + let mut map = csky::regclass_map(); + csky::fill_reg_map(arch, reloc_model, target_features, target, &mut map); + map + } } } diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs new file mode 100644 index 00000000000..181cad0163a --- /dev/null +++ b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs @@ -0,0 +1,22 @@ +use crate::spec::{Target, TargetOptions}; + +// This target is for glibc Linux on Csky +// hardfloat. + +pub fn target() -> Target { + Target { + //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h + llvm_target: "csky-unknown-linux".into(), + pointer_width: 32, + data_layout: "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32".into(), + arch: "csky".into(), + options: TargetOptions { + abi: "abiv2".into(), + //+hard-float, +hard-float-abi, +fpuv2_sf, +fpuv2_df, +fpuv3_sf, +fpuv3_df, +vdspv2, +dspv2, +vdspv1, +3e3r1 + features: "".into(), + max_atomic_width: Some(32), + // mcount: "\u{1}__gnu_mcount_nc".into(), + ..super::linux_gnu_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1871239d7de..6ada4e49083 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1246,6 +1246,7 @@ supported_targets! { ("i586-unknown-linux-gnu", i586_unknown_linux_gnu), ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu), ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu), + ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2), ("mips-unknown-linux-gnu", mips_unknown_linux_gnu), ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64), ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64), diff --git a/config.example.toml b/config.example.toml index fc5de5f9537..5c4bee87553 100644 --- a/config.example.toml +++ b/config.example.toml @@ -94,7 +94,7 @@ changelog-seen = 2 # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. -#experimental-targets = "AVR;M68k" +#experimental-targets = "AVR;M68k;CSKY" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 3fcd5e7c1cb..b2c9a0800c9 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -110,7 +110,8 @@ mod c_char_definition { target_arch = "powerpc64", target_arch = "s390x", target_arch = "riscv64", - target_arch = "riscv32" + target_arch = "riscv32", + target_arch = "csky" ) ), all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), diff --git a/library/std/src/env.rs b/library/std/src/env.rs index f3122c2931d..f67f6034d34 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -894,6 +894,7 @@ pub mod consts { /// - aarch64 /// - loongarch64 /// - m68k + /// - csky /// - mips /// - mips64 /// - powerpc diff --git a/library/std/src/os/l4re/raw.rs b/library/std/src/os/l4re/raw.rs index b3f7439f8cd..12c0293285a 100644 --- a/library/std/src/os/l4re/raw.rs +++ b/library/std/src/os/l4re/raw.rs @@ -27,6 +27,7 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; #[cfg(any( target_arch = "x86", target_arch = "m68k", + target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "arm", diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs index 7c55e92502f..a568f9b26ba 100644 --- a/library/std/src/os/linux/raw.rs +++ b/library/std/src/os/linux/raw.rs @@ -27,6 +27,7 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; #[cfg(any( target_arch = "x86", target_arch = "m68k", + target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "arm", diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index 3ccea3ce0e3..d58aa6c27b8 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -8,6 +8,7 @@ use crate::ptr; target_arch = "x86", target_arch = "arm", target_arch = "m68k", + target_arch = "csky", target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index dc9636ac8c9..e477a0cd7ab 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -67,6 +67,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // D0, D1 ))] const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1 +#[cfg(target_arch = "csky")] +const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4 diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 521da6c4589..a2bfa8e96dd 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -54,6 +54,9 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] pub const unwinder_private_data_size: usize = 2; +#[cfg(target_arch = "csky")] +pub const unwinder_private_data_size: usize = 2; + #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))] pub const unwinder_private_data_size: usize = 2; diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 70079106689..f44a05a6b28 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -332,6 +332,7 @@ def default_build_triple(verbose): 'i786': 'i686', 'loongarch64': 'loongarch64', 'm68k': 'm68k', + 'csky': 'csky', 'powerpc': 'powerpc', 'powerpc64': 'powerpc64', 'powerpc64le': 'powerpc64le', diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index e3a9434a164..4396bbc51a3 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -138,7 +138,7 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)] ( Some(Mode::Std), "target_arch", - Some(&["asmjs", "spirv", "nvptx", "xtensa", "mips32r6", "mips64r6"]), + Some(&["asmjs", "spirv", "nvptx", "xtensa", "mips32r6", "mips64r6", "csky"]), ), /* Extra names used by dependencies */ // FIXME: Used by serde_json, but we should not be triggering on external dependencies. diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 4943f93fa9a..7acf657f630 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -299,7 +299,7 @@ impl Step for Llvm { let llvm_exp_targets = match builder.config.llvm_experimental_targets { Some(ref s) => s, - None => "AVR;M68k", + None => "AVR;M68k;CSKY", }; let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" }; diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 817abbfaf26..94605e2a217 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -32,6 +32,7 @@ - [\*-esp-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) + - [csky-unknown-linux-gnuabiv2](platform-support/csky-unknown-linux-gnuabiv2.md) - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md) - [loongarch\*-unknown-none\*](platform-support/loongarch-none.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 393719e7115..a78b5314fcc 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -259,6 +259,7 @@ target | std | host | notes `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) +`csky-unknown-linux-gnuabiv2` | ? | | C-SKY iv2 Linux `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md new file mode 100644 index 00000000000..a407fdc8c71 --- /dev/null +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -0,0 +1,33 @@ +# `csky-unknown-linux-gnuabiv2` + +**Tier: 3** + +This target supports [C-SKY](https://github.com/c-sky) v2 CPUs with `glibc`. + +https://c-sky.github.io/ +## Target maintainers + +* [@Dirreke](https://github.com/Dirreke) + +## Requirements + + +## Building the target + +add `csky-unknown-linux-gnuabiv2` to the `target` list in `config.toml` and `./x build`. + +## Building Rust programs + +Rust programs can be built for that target: + +```text +cargo +stage2 --target csky-unknown-linux-gnuabiv2 your-code.rs +``` + +## Testing + +Currently there is no support to run the rustc test suite for this target. + +## Cross-compilation toolchains and C code + +This target can be cross-compiled from `x86_64` on either Linux systems with [`csky-linux-gunabiv2-tools-x86_64-glibc-linux`](https://github.com/c-sky/toolchain-build). diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index c634dc50d6d..d52287051c6 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -17,6 +17,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - AVR - MSP430 - M68k +- CSKY - s390x ## Register classes @@ -46,6 +47,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `reg` | `d[0-7]`, `a[0-7]` | `r` | | M68k | `reg_data` | `d[0-7]` | `d` | | M68k | `reg_addr` | `a[0-3]` | `a` | +| CSKY | `reg` | `r[0-31]` | `r` | +| CSKY | `freg` | `f[0-31]` | `f` | | s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | | s390x | `freg` | `f[0-15]` | `f` | @@ -79,6 +82,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | MSP430 | `reg` | None | `i8`, `i16` | | M68k | `reg`, `reg_addr` | None | `i16`, `i32` | | M68k | `reg_data` | None | `i8`, `i16`, `i32` | +| CSKY | `reg` | None | `i8`, `i16`, `i32`, `i64` | +| CSKY | `freg` | None | `f32`, `f64` | | s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | @@ -102,6 +107,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `a5` | `bp` | | M68k | `a6` | `fp` | | M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| CSKY | `r14` | `sp` | +| CSKY | `r15` | `lr` | +| CSKY | `r28` | `gb`, `rgb`, `rdb` | +| CSKY | `r31` | `tls` | > **Notes**: > - TI does not mandate a frame pointer for MSP430, but toolchains are allowed diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 83886dd42aa..7652f27e51c 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -519,6 +519,7 @@ impl<'a> fmt::Display for Display<'a> { "asmjs" => "JavaScript", "loongarch64" => "LoongArch LA64", "m68k" => "M68k", + "csky" => "CSKY", "mips" => "MIPS", "mips32r6" => "MIPS Release 6", "mips64" => "MIPS-64", diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 88f8770029e..778609da062 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -100,6 +100,7 @@ static TARGETS: &[&str] = &[ "i686-unknown-uefi", "loongarch64-unknown-linux-gnu", "m68k-unknown-linux-gnu", + "csky-unknown-linux-gnuabiv2", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips64-unknown-linux-gnuabi64", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs index 19bfd294b25..a5af9affb9c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs @@ -46,6 +46,7 @@ const KNOWN_ARCH: [&str; 19] = [ "aarch64", "arm", "avr", + "csky", "hexagon", "mips", "mips64", -- cgit 1.4.1-3-g733a5 From 184a9afffbc7ba23409ca071d86b34ad74f50b17 Mon Sep 17 00:00:00 2001 From: Dirreke Date: Wed, 19 Jul 2023 22:33:34 +0800 Subject: add details for csky-unknown-linux-gnuabiv2 and add docs --- compiler/rustc_codegen_llvm/src/asm.rs | 2 +- compiler/rustc_codegen_ssa/src/target_features.rs | 48 ++++++++++++++++--- compiler/rustc_target/src/asm/csky.rs | 48 +++++++------------ .../src/spec/csky_unknown_linux_gnuabiv2.rs | 8 ++-- src/bootstrap/llvm.rs | 16 +++++++ src/doc/rustc/src/platform-support.md | 2 +- .../csky-unknown-linux-gnuabiv2.md | 55 ++++++++++++++++++---- .../src/language-features/asm-experimental-arch.md | 22 +++++++-- 8 files changed, 145 insertions(+), 56 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 4d7db96cc82..ca9fd76a997 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -261,7 +261,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { InlineAsmArch::M68k => { constraints.push("~{ccr}".to_string()); } - InlineAsmArch::CSKY => {} // https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h getClobers() + InlineAsmArch::CSKY => {} } } if !options.contains(InlineAsmOptions::NOMEM) { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index f1571dd2219..baf6b19d3f9 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -297,14 +297,50 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ const BPF_ALLOWED_FEATURES: &[(&str, Option)] = &[("alu32", Some(sym::bpf_target_feature))]; const CSKY_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("hard-float", Some(sym::csky_target_feature)), - ("hard-float-abi", Some(sym::csky_target_feature)), - ("fpuv2_sf", Some(sym::csky_target_feature)), + // tidy-alphabetical-start + ("10e60", Some(sym::csky_target_feature)), + ("2e3", Some(sym::csky_target_feature)), + ("3e3r1", Some(sym::csky_target_feature)), + ("3e3r2", Some(sym::csky_target_feature)), + ("3e3r3", Some(sym::csky_target_feature)), + ("3e7", Some(sym::csky_target_feature)), + ("7e10", Some(sym::csky_target_feature)), + ("cache", Some(sym::csky_target_feature)), + ("doloop", Some(sym::csky_target_feature)), + ("dsp1e2", Some(sym::csky_target_feature)), + ("dspe60", Some(sym::csky_target_feature)), + ("e1", Some(sym::csky_target_feature)), + ("e2", Some(sym::csky_target_feature)), + ("edsp", Some(sym::csky_target_feature)), + ("elrw", Some(sym::csky_target_feature)), + ("float1e2", Some(sym::csky_target_feature)), + ("float1e3", Some(sym::csky_target_feature)), + ("float3e4", Some(sym::csky_target_feature)), + ("float7e60", Some(sym::csky_target_feature)), + ("floate1", Some(sym::csky_target_feature)), + ("hard-tp", Some(sym::csky_target_feature)), + ("high-registers", Some(sym::csky_target_feature)), + ("hwdiv", Some(sym::csky_target_feature)), + ("mp", Some(sym::csky_target_feature)), + ("mp1e2", Some(sym::csky_target_feature)), + ("nvic", Some(sym::csky_target_feature)), + ("trust", Some(sym::csky_target_feature)), + ("vdsp2e60f", Some(sym::csky_target_feature)), + ("vdspv1", Some(sym::csky_target_feature)), + ("vdspv2", Some(sym::csky_target_feature)), + // tidy-alphabetical-end + //fpu + // tidy-alphabetical-start + ("fdivdu", Some(sym::csky_target_feature)), ("fpuv2_df", Some(sym::csky_target_feature)), - ("fpuv3_sf", Some(sym::csky_target_feature)), + ("fpuv2_sf", Some(sym::csky_target_feature)), ("fpuv3_df", Some(sym::csky_target_feature)), - ("vdspv2", Some(sym::csky_target_feature)), - ("dspv2", Some(sym::csky_target_feature)), + ("fpuv3_hf", Some(sym::csky_target_feature)), + ("fpuv3_hi", Some(sym::csky_target_feature)), + ("fpuv3_sf", Some(sym::csky_target_feature)), + ("hard-float", Some(sym::csky_target_feature)), + ("hard-float-abi", Some(sym::csky_target_feature)), + // tidy-alphabetical-end ]; /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. diff --git a/compiler/rustc_target/src/asm/csky.rs b/compiler/rustc_target/src/asm/csky.rs index 13bb846c731..6f0e7f79949 100644 --- a/compiler/rustc_target/src/asm/csky.rs +++ b/compiler/rustc_target/src/asm/csky.rs @@ -36,8 +36,8 @@ impl CSKYInlineAsmRegClass { _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option)] { match self { - Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, - Self::freg => types! { _: F32, F64; }, + Self::reg => types! { _: I8, I16, I32; }, + Self::freg => types! { _: F32; }, } } } @@ -52,31 +52,21 @@ def_regs! { r4: reg = ["r4","l0"], r5: reg = ["r5","l1"], r6: reg = ["r6","l2"], - // r7: reg = ["r7","l3"], - // r8: reg = ["r8","l4"], - // r9: reg = ["r9","l5"], - // r10: reg = ["r10","l6"], - // r11: reg = ["r11","l7"], - // r12: reg = ["r12","t0"], - // r13: reg = ["r13","t1"], - // r14: reg = ["r14","sp"], - // r15: reg = ["r15","lr"], - // r16: reg = ["r16","l8"], - // r17: reg = ["r17","l9"], - // r18: reg = ["r18","t2"], - // r19: reg = ["r19","t3"], - // r20: reg = ["r20","t4"], - // r21: reg = ["r21","t5"], - // r22: reg = ["r22","t6"], - // r23: reg = ["r23","t7", "fp"], - // r24: reg = ["r24","t8", "sop"], - // r25: reg = ["r25","tp", "bsp"], - // r26: reg = ["r26"], - // r27: reg = ["r27"], - // r28: reg = ["r28","gb", "rgb", "rdb"], - // r29: reg = ["r29","tb", "rtb"], - // r30: reg = ["r30","svbr"], - // r31: reg = ["r31","tls"], + r9: reg = ["r9","l5"],// feature e2 + r10: reg = ["r10","l6"],// feature e2 + r11: reg = ["r11","l7"],// feature e2 + r12: reg = ["r12","t0"],// feature e2 + r13: reg = ["r13","t1"],// feature e2 + r16: reg = ["r16","l8"],// feature high-register + r17: reg = ["r17","l9"],// feature high-register + r18: reg = ["r18","t2"],// feature high-register + r19: reg = ["r19","t3"],// feature high-register + r20: reg = ["r20","t4"],// feature high-register + r21: reg = ["r21","t5"],// feature high-register + r22: reg = ["r22","t6"],// feature high-register + r23: reg = ["r23","t7", "fp"],// feature high-register + r24: reg = ["r24","t8", "sop"],// feature high-register + r25: reg = ["r25","t9","tp", "bsp"],// feature high-register f0: freg = ["fr0","vr0"], f1: freg = ["fr1","vr1"], f2: freg = ["fr2","vr2"], @@ -121,10 +111,6 @@ def_regs! { "reserver for tls", #error = ["r28", "gb", "rgb", "rdb"] => "the global pointer cannot be used as an operand for inline asm", - #error = ["r9","l5", "r10","l6", "r11","l7", "r12","t0", "r13","t1"] => - "reserved (no E2)", - #error = ["r16","l8", "r17","l9", "r18","t2", "r19","t3", "r20","t4", "r21","t5", "r22","t6", "r23","t7", "fp", "r24","t8", "sop", "r25","tp", "bsp"] => - "reserved (no HighRegisters)", #error = ["r26","r27","r29","tb", "rtb", "r30","svbr"] => "reserved by the ABI", } diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs index 3bc075f6920..7d03dd26f5d 100644 --- a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs +++ b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs @@ -1,7 +1,6 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target is for glibc Linux on Csky -// hardfloat. pub fn target() -> Target { Target { @@ -12,10 +11,9 @@ pub fn target() -> Target { arch: "csky".into(), options: TargetOptions { abi: "abiv2".into(), - //+hard-float, +hard-float-abi, +fpuv2_sf, +fpuv2_df, +fpuv3_sf, +fpuv3_df, +vdspv2, +dspv2, +vdspv1, +3e3r1 - features: "".into(), + features: "+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(), + late_link_args_static: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a"]), max_atomic_width: Some(32), - // mcount: "\u{1}__gnu_mcount_nc".into(), ..super::linux_gnu_base::opts() }, } diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 7acf657f630..da7ff626cb2 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -390,6 +390,22 @@ impl Step for Llvm { ldflags.shared.push(" -latomic"); } + if target.starts_with("csky") + && !target.contains("freebsd") + && !target.contains("openbsd") + && !target.contains("netbsd") + { + // CSKY GCC erroneously requires linking against + // `libatomic` when using 1-byte and 2-byte C++ + // atomics but the LLVM build system check cannot + // detect this. Therefore it is set manually here. + // Some BSD uses Clang as its system compiler and + // provides no libatomic in its base system so does + // not want this. + ldflags.exe.push(" -latomic"); + ldflags.shared.push(" -latomic"); + } + if target.contains("msvc") { cfg.define("LLVM_USE_CRT_DEBUG", "MT"); cfg.define("LLVM_USE_CRT_RELEASE", "MT"); diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index a78b5314fcc..371ee378d1a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -259,7 +259,7 @@ target | std | host | notes `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) -`csky-unknown-linux-gnuabiv2` | ? | | C-SKY iv2 Linux +`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux(little endian) `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md index 240d58596cf..e73598be0d9 100644 --- a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -5,6 +5,8 @@ This target supports [C-SKY](https://github.com/c-sky) CPUs with `abi` v2 and `glibc`. https://c-sky.github.io/ +https://gitlab.com/c-sky/ + ## Target maintainers * [@Dirreke](https://github.com/Dirreke) @@ -14,20 +16,55 @@ https://c-sky.github.io/ ## Building the target -add `csky-unknown-linux-gnuabiv2` to the `target` list in `config.toml` and `./x build`. +### Get a C toolchain + +Compiling rust for this target has been tested on `x86_64` linux hosts. Other host types have not been tested, but may work, if you can find a suitable cross compilation toolchain for them. + +If you don't already have a suitable toolchain, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource/1356021/1619528643136/csky-linux-gnuabiv2-tools-x86_64-glibc-linux-4.9.56-20210423.tar.gz), and unpack it into a directory. + +### Configure rust + +The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`: + +```toml +[build] +target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2"] +stage = 2 -## Building Rust programs +[target.csky-unknown-linux-gnuabiv2] +# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN +cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc" -Rust programs can be built for that target: +### Build -```text -cargo +stage2 --target csky-unknown-linux-gnuabiv2 your-code.rs +```sh +# in rust dir +./x.py build --stage 2 ``` -## Testing +## Building and Running Rust programs -Currently there is no support to run the rustc test suite for this target. +To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-cskyv2`. This avoids having a full emulated ARM system by doing dynamic binary translation and dynamic system call translation. It lets you run CSKY programs directly on your `x86_64` kernel. It's very convenient! -## Cross-compilation toolchains and C code +To use: + +* Install `qemu-cskyv2` (If you don't already have a qemu, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1689324918932/xuantie-qemu-x86_64-Ubuntu-18.04-20230714-0202.tar.gz"), and unpack it into a directory.) +* Link your built toolchain via: + * `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2` +* Create a test program + +```sh +cargo new hello_world +cd hello_world +``` + +* Build and run + +```sh +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_RUNNER=${QEMU_PATH}/bin/qemu-cskyv2 -L ${TOOLCHAIN_PATH}/csky-linux-gnuabiv2/libc \ +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_LINKER=${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc \ +RUSTFLAGS="-C target-features=+crt-static" \ +cargo +stage2 run --target csky-unknown-linux-gnuabiv2 +``` -This target can be cross-compiled from `x86_64` on either Linux systems with [`csky-linux-gunabiv2-tools-x86_64-glibc-linux`](https://github.com/c-sky/toolchain-build). +Attention: The dynamic-linked program may nor be run by `qemu-cskyv2` but can be run on the target. diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index d52287051c6..968c9bb4ebb 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -82,8 +82,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | MSP430 | `reg` | None | `i8`, `i16` | | M68k | `reg`, `reg_addr` | None | `i16`, `i32` | | M68k | `reg_data` | None | `i8`, `i16`, `i32` | -| CSKY | `reg` | None | `i8`, `i16`, `i32`, `i64` | -| CSKY | `freg` | None | `f32`, `f64` | +| CSKY | `reg` | None | `i8`, `i16`, `i32` | +| CSKY | `freg` | None | `f32`, | | s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | @@ -107,9 +107,16 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `a5` | `bp` | | M68k | `a6` | `fp` | | M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| CSKY | `r[0-3]` | `a[0-3]` | +| CSKY | `r[4-11]` | `l[0-7]` | +| CSKY | `r[12-13]` | `t[0-1]` | | CSKY | `r14` | `sp` | | CSKY | `r15` | `lr` | -| CSKY | `r28` | `gb`, `rgb`, `rdb` | +| CSKY | `r[16-17]` | `l[8-9]` | +| CSKY | `r[18-25]` | `t[2-9]` | +| CSKY | `r28` | `rgb` | +| CSKY | `r29` | `rtb` | +| CSKY | `r30` | `svbr` | | CSKY | `r31` | `tls` | > **Notes**: @@ -132,6 +139,13 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | |MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | | M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r7`, `r28` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r8` | Used internally by LLVM for the frame pointer. | +| CSKY | `r14` | Used internally by LLVM for the stack pointer. | +| CSKY | `r15` | This is the link register. | +| CSKY | `r[26-30]` | Reserved by its ABI. | +| CSKY | `r31` | This is the TLS register. | + ## Template modifiers @@ -148,6 +162,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `freg` | None | `0` | None | | s390x | `reg` | None | `%r0` | None | | s390x | `freg` | None | `%f0` | None | +| CSKY | `reg` | None | `r0` | None | +| CSKY | `freg` | None | `f0` | None | # Flags covered by `preserves_flags` -- cgit 1.4.1-3-g733a5