From 3f1304a55e3653f2546d183369c787ebd812ee19 Mon Sep 17 00:00:00 2001 From: sapir Date: Tue, 6 Aug 2024 00:09:19 +0300 Subject: [PATCH] Implement int extension --- src/builder.rs | 8 ++++---- src/context.rs | 27 ++++++++++++++++++++++++++- src/int.rs | 16 ++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index e7f1e7e6b90..2b36399ddcf 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1219,7 +1219,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // TODO(antoyo): nothing to do as it is only for LLVM? return value; } - self.context.new_cast(self.location, value, dest_ty) + + self.extend_int(value, dest_ty, true) } fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { @@ -1700,9 +1701,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { call } - fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): this does not zero-extend. - self.gcc_int_cast(value, dest_typ) + fn zext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.extend_int(value, dest_ty, false) } fn cx(&self) -> &CodegenCx<'gcc, 'tcx> { diff --git a/src/context.rs b/src/context.rs index 4458ca84bbb..5a713501825 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,12 +10,12 @@ use rustc_data_structures::base_n::ToBaseN; use rustc_data_structures::base_n::ALPHANUMERIC_ONLY; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::mono::CodegenUnit; -use rustc_middle::span_bug; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::Session; use rustc_span::{source_map::respan, Span}; use rustc_target::abi::{ @@ -360,6 +360,31 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { function } + pub fn get_matching_int_type(&self, typ: Type<'gcc>, signed: bool) -> Type<'gcc> { + let size = if typ.is_compatible_with(self.bool_type) { + // For booleans, return an 8-bit integer instead. + 1 + } else { + typ.get_size() + }; + + match (size, signed) { + (1, false) => self.u8_type, + (2, false) => self.u16_type, + (4, false) => self.u32_type, + (8, false) => self.u64_type, + (16, false) => self.u128_type, + (1, true) => self.i8_type, + (2, true) => self.i16_type, + (4, true) => self.i32_type, + (8, true) => self.i64_type, + (16, true) => self.i128_type, + _ => { + bug!("attempt to get bad int type {}{}", if signed { 'i' } else { 'u' }, size * 8); + } + } + } + pub fn is_native_int_type(&self, typ: Type<'gcc>) -> bool { let types = [ self.u8_type, diff --git a/src/int.rs b/src/int.rs index e4c5eb91373..51c5476605d 100644 --- a/src/int.rs +++ b/src/int.rs @@ -5,6 +5,7 @@ use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp}; +use rustc_middle::bug; use rustc_middle::ty::{ParamEnv, Ty}; use rustc_target::abi::{ call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}, @@ -866,6 +867,21 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc) } + pub fn extend_int( + &self, + value: RValue<'gcc>, + dest_ty: Type<'gcc>, + signed: bool, + ) -> RValue<'gcc> { + let src_ty = value.get_type(); + if !self.is_int_type_or_bool(src_ty) || !self.is_int_type_or_bool(dest_ty) { + bug!("got extend_int for non-int type {:?} -> {:?}", src_ty, dest_ty); + } + + let intermediate_ty = self.get_matching_int_type(src_ty, signed); + self.gcc_int_cast(self.gcc_int_cast(value, intermediate_ty), dest_ty) + } + // TODO(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { let value_type = value.get_type();