From a6bd5ae57eb0421373a4f3aa69ac56fb5c549383 Mon Sep 17 00:00:00 2001 From: David Craven Date: Tue, 24 Jul 2018 12:04:17 +0200 Subject: [PATCH] [RISCV] Implement call abi. --- src/librustc_target/abi/call/mod.rs | 3 ++ src/librustc_target/abi/call/riscv.rs | 59 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/librustc_target/abi/call/riscv.rs diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index ca5aba5b642..f65fa341231 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -23,6 +23,7 @@ mod nvptx; mod nvptx64; mod powerpc; mod powerpc64; +mod riscv; mod s390x; mod sparc; mod sparc64; @@ -500,6 +501,8 @@ impl<'a, Ty> FnType<'a, Ty> { "nvptx" => nvptx::compute_abi_info(self), "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), + "riscv32" => riscv::compute_abi_info(self, 32), + "riscv64" => riscv::compute_abi_info(self, 64), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_target/abi/call/riscv.rs b/src/librustc_target/abi/call/riscv.rs new file mode 100644 index 00000000000..fe0d7485c15 --- /dev/null +++ b/src/librustc_target/abi/call/riscv.rs @@ -0,0 +1,59 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Reference: RISC-V ELF psABI specification +// https://github.com/riscv/riscv-elf-psabi-doc + +use abi::call::{ArgType, FnType}; + +fn classify_ret_ty(arg: &mut ArgType, xlen: u64) { + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if arg.layout.size.bits() > 2 * xlen { + arg.make_indirect(); + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + arg.extend_integer_width_to(xlen); // this method only affects integer scalars +} + +fn classify_arg_ty(arg: &mut ArgType, xlen: u64) { + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if arg.layout.size.bits() > 2 * xlen { + arg.make_indirect(); + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + arg.extend_integer_width_to(xlen); // this method only affects integer scalars +} + +pub fn compute_abi_info(fty: &mut FnType, xlen: u64) { + if !fty.ret.is_ignore() { + classify_ret_ty(&mut fty.ret, xlen); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(arg, xlen); + } +}