Merge branch 'main' into clippy-1.74

This commit is contained in:
Ayaz 2023-12-02 20:09:06 -06:00 committed by GitHub
commit aaba3f4d82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
320 changed files with 11155 additions and 18862 deletions

View file

@ -365,6 +365,7 @@ impl CallConv<AArch64GeneralReg, AArch64FloatReg, AArch64Assembler> for AArch64C
/// 213568: f90033fd str x29, [sp, #96]
const SHADOW_SPACE_SIZE: u8 = 16;
// These are registers that a called function must save and restore if it wants to use them.
#[inline(always)]
fn general_callee_saved(reg: &AArch64GeneralReg) -> bool {
matches!(

View file

@ -82,8 +82,8 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
fn setup_stack(
buf: &mut Vec<'_, u8>,
general_saved_regs: &[GeneralReg],
float_saved_regs: &[FloatReg],
saved_general_regs: &[GeneralReg],
saved_float_regs: &[FloatReg],
requested_stack_size: i32,
fn_call_stack_size: i32,
) -> i32;
@ -900,8 +900,11 @@ impl<
let mut out = bumpalo::vec![in self.env.arena];
// Setup stack.
let used_general_regs = self.storage_manager.general_used_callee_saved_regs();
let used_float_regs = self.storage_manager.float_used_callee_saved_regs();
let (used_general_regs, used_float_regs) = self
.storage_manager
.used_callee_saved_regs
.as_vecs(self.env.arena);
let aligned_stack_size = CC::setup_stack(
&mut out,
&used_general_regs,
@ -1199,6 +1202,12 @@ impl<
max_branch_stack_size =
std::cmp::max(max_branch_stack_size, self.storage_manager.stack_size());
base_storage.update_fn_call_stack_size(self.storage_manager.fn_call_stack_size());
// make sure that used callee-saved registers get saved/restored even if used in only
// one of the branches of the switch
base_storage
.used_callee_saved_regs
.extend(&self.storage_manager.used_callee_saved_regs);
}
self.storage_manager = base_storage;
self.literal_map = base_literal_map;

View file

@ -3,7 +3,7 @@ use crate::{
pointer_layouts, sign_extended_int_builtins, single_register_floats,
single_register_int_builtins, single_register_integers, single_register_layouts, Env,
};
use bumpalo::collections::Vec;
use bumpalo::collections::{CollectIn, Vec};
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_collections::all::{MutMap, MutSet};
use roc_error_macros::{internal_error, todo_lambda_erasure};
@ -118,10 +118,7 @@ pub struct StorageManager<
general_used_regs: Vec<'a, (GeneralReg, Symbol)>,
float_used_regs: Vec<'a, (FloatReg, Symbol)>,
// TODO: it probably would be faster to make these a list that linearly scans rather than hashing.
// used callee saved regs must be tracked for pushing and popping at the beginning/end of the function.
general_used_callee_saved_regs: MutSet<GeneralReg>,
float_used_callee_saved_regs: MutSet<FloatReg>,
pub(crate) used_callee_saved_regs: UsedCalleeRegisters<GeneralReg, FloatReg>,
free_stack_chunks: Vec<'a, (i32, u32)>,
stack_size: u32,
@ -152,16 +149,62 @@ pub fn new_storage_manager<
join_param_map: MutMap::default(),
general_free_regs: bumpalo::vec![in env.arena],
general_used_regs: bumpalo::vec![in env.arena],
general_used_callee_saved_regs: MutSet::default(),
// must be saved on entering a function, and restored before returning
used_callee_saved_regs: UsedCalleeRegisters::default(),
float_free_regs: bumpalo::vec![in env.arena],
float_used_regs: bumpalo::vec![in env.arena],
float_used_callee_saved_regs: MutSet::default(),
free_stack_chunks: bumpalo::vec![in env.arena],
stack_size: 0,
fn_call_stack_size: 0,
}
}
// optimization idea: use a bitset
#[derive(Debug, Clone)]
pub(crate) struct UsedCalleeRegisters<GeneralReg, FloatReg> {
general: MutSet<GeneralReg>,
float: MutSet<FloatReg>,
}
impl<GeneralReg: RegTrait, FloatReg: RegTrait> UsedCalleeRegisters<GeneralReg, FloatReg> {
fn clear(&mut self) {
self.general.clear();
self.float.clear();
}
fn insert_general(&mut self, reg: GeneralReg) -> bool {
self.general.insert(reg)
}
fn insert_float(&mut self, reg: FloatReg) -> bool {
self.float.insert(reg)
}
pub(crate) fn extend(&mut self, other: &Self) {
self.general.extend(other.general.iter().copied());
self.float.extend(other.float.iter().copied());
}
pub(crate) fn as_vecs<'a>(
&self,
arena: &'a bumpalo::Bump,
) -> (Vec<'a, GeneralReg>, Vec<'a, FloatReg>) {
(
self.general.iter().copied().collect_in(arena),
self.float.iter().copied().collect_in(arena),
)
}
}
impl<GeneralReg, FloatReg> Default for UsedCalleeRegisters<GeneralReg, FloatReg> {
fn default() -> Self {
Self {
general: Default::default(),
float: Default::default(),
}
}
}
impl<
'a,
'r,
@ -175,16 +218,16 @@ impl<
self.symbol_storage_map.clear();
self.allocation_map.clear();
self.join_param_map.clear();
self.general_used_callee_saved_regs.clear();
self.used_callee_saved_regs.clear();
self.general_free_regs.clear();
self.general_used_regs.clear();
self.general_free_regs
.extend_from_slice(CC::GENERAL_DEFAULT_FREE_REGS);
self.float_used_callee_saved_regs.clear();
self.float_free_regs.clear();
self.float_used_regs.clear();
self.float_free_regs
.extend_from_slice(CC::FLOAT_DEFAULT_FREE_REGS);
self.used_callee_saved_regs.clear();
self.free_stack_chunks.clear();
self.stack_size = 0;
self.fn_call_stack_size = 0;
@ -198,18 +241,6 @@ impl<
self.fn_call_stack_size
}
pub fn general_used_callee_saved_regs(&self) -> Vec<'a, GeneralReg> {
let mut used_regs = bumpalo::vec![in self.env.arena];
used_regs.extend(&self.general_used_callee_saved_regs);
used_regs
}
pub fn float_used_callee_saved_regs(&self) -> Vec<'a, FloatReg> {
let mut used_regs = bumpalo::vec![in self.env.arena];
used_regs.extend(&self.float_used_callee_saved_regs);
used_regs
}
/// Returns true if the symbol is storing a primitive value.
pub fn is_stored_primitive(&self, sym: &Symbol) -> bool {
matches!(
@ -223,7 +254,7 @@ impl<
fn get_general_reg(&mut self, buf: &mut Vec<'a, u8>) -> GeneralReg {
if let Some(reg) = self.general_free_regs.pop() {
if CC::general_callee_saved(&reg) {
self.general_used_callee_saved_regs.insert(reg);
self.used_callee_saved_regs.insert_general(reg);
}
reg
} else if !self.general_used_regs.is_empty() {
@ -240,7 +271,7 @@ impl<
fn get_float_reg(&mut self, buf: &mut Vec<'a, u8>) -> FloatReg {
if let Some(reg) = self.float_free_regs.pop() {
if CC::float_callee_saved(&reg) {
self.float_used_callee_saved_regs.insert(reg);
self.used_callee_saved_regs.insert_float(reg);
}
reg
} else if !self.float_used_regs.is_empty() {

View file

@ -199,6 +199,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
];
const SHADOW_SPACE_SIZE: u8 = 0;
// These are registers that a called function must save and restore if it wants to use them.
#[inline(always)]
fn general_callee_saved(reg: &X86_64GeneralReg) -> bool {
matches!(
@ -1409,6 +1410,8 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
];
const SHADOW_SPACE_SIZE: u8 = 32;
// These are registers that a called function must save and restore if it wants to use them.
//
// Refer https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers
// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile.
// > They must be saved and restored by a function that uses them.

View file

@ -57,6 +57,14 @@ impl AssemblyBackendMode {
AssemblyBackendMode::Repl => true,
}
}
fn generate_roc_dbg(self) -> bool {
match self {
AssemblyBackendMode::Binary => false,
AssemblyBackendMode::Test => true,
AssemblyBackendMode::Repl => true,
}
}
}
pub struct Env<'a> {
@ -182,7 +190,7 @@ impl<'a> LastSeenMap<'a> {
Expr::UnionAtIndex { structure, .. } => {
self.set_last_seen(*structure, stmt);
}
Expr::UnionFieldPtrAtIndex { structure, .. } => {
Expr::GetElementPointer { structure, .. } => {
self.set_last_seen(*structure, stmt);
}
Expr::Array { elems, .. } => {
@ -849,13 +857,20 @@ trait Backend<'a> {
} => {
self.load_union_at_index(sym, structure, *tag_id, *index, union_layout);
}
Expr::UnionFieldPtrAtIndex {
Expr::GetElementPointer {
structure,
tag_id,
union_layout,
index,
indices,
..
} => {
self.load_union_field_ptr_at_index(sym, structure, *tag_id, *index, union_layout);
debug_assert!(indices.len() >= 2);
self.load_union_field_ptr_at_index(
sym,
structure,
indices[0] as u16,
indices[1],
union_layout,
);
}
Expr::GetTagId {
structure,

View file

@ -296,6 +296,23 @@ fn generate_roc_panic<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object)
}
}
fn generate_roc_dbg<'a, B: Backend<'a>>(_backend: &mut B, output: &mut Object) {
let text_section = output.section_id(StandardSection::Text);
let proc_symbol = Symbol {
name: "roc_dbg".as_bytes().to_vec(),
value: 0,
size: 0,
kind: SymbolKind::Text,
scope: SymbolScope::Dynamic,
weak: false,
section: SymbolSection::Section(text_section),
flags: SymbolFlags::None,
};
let _proc_id = output.add_symbol(proc_symbol);
// TODO: Actually generate an impl instead of just an empty symbol.
// At a minimum, it should just be a ret.
}
fn generate_wrapper<'a, B: Backend<'a>>(
backend: &mut B,
output: &mut Object,
@ -412,6 +429,10 @@ fn build_object<'a, B: Backend<'a>>(
generate_longjmp(&mut backend, &mut output);
}
if backend.env().mode.generate_roc_dbg() {
generate_roc_dbg(&mut backend, &mut output);
}
if backend.env().mode.generate_allocators() {
generate_wrapper(
&mut backend,