Merge branch 'master' into sync_from_rust_2024_07_02
This commit is contained in:
commit
05a41b88a9
53 changed files with 1767 additions and 947 deletions
15
src/abi.rs
15
src/abi.rs
|
|
@ -4,6 +4,7 @@ use gccjit::{ToLValue, ToRValue, Type};
|
|||
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::Ty;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_session::config;
|
||||
|
|
@ -184,9 +185,17 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
}
|
||||
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
|
||||
assert!(!on_stack);
|
||||
let ty =
|
||||
apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
|
||||
apply_attrs(ty, &meta_attrs, argument_tys.len())
|
||||
// Construct the type of a (wide) pointer to `ty`, and pass its two fields.
|
||||
// Any two ABI-compatible unsized types have the same metadata type and
|
||||
// moreover the same metadata value leads to the same dynamic size and
|
||||
// alignment, so this respects ABI compatibility.
|
||||
let ptr_ty = Ty::new_mut_ptr(cx.tcx, arg.layout.ty);
|
||||
let ptr_layout = cx.layout_of(ptr_ty);
|
||||
let typ1 = ptr_layout.scalar_pair_element_gcc_type(cx, 0);
|
||||
let typ2 = ptr_layout.scalar_pair_element_gcc_type(cx, 1);
|
||||
argument_tys.push(apply_attrs(typ1, &attrs, argument_tys.len()));
|
||||
argument_tys.push(apply_attrs(typ2, &meta_attrs, argument_tys.len()));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
argument_tys.push(arg_ty);
|
||||
|
|
|
|||
56
src/asm.rs
56
src/asm.rs
|
|
@ -115,7 +115,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
span: &[Span],
|
||||
instance: Instance<'_>,
|
||||
dest: Option<Self::BasicBlock>,
|
||||
_catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>,
|
||||
_dest_catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>,
|
||||
) {
|
||||
if options.contains(InlineAsmOptions::MAY_UNWIND) {
|
||||
self.sess().dcx().create_err(UnwindingInlineAsm { span: span[0] }).emit();
|
||||
|
|
@ -485,9 +485,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
InlineAsmOperandRef::Label { label } => {
|
||||
let label_gcc_index = labels.iter()
|
||||
.position(|&l| l == label)
|
||||
.expect("wrong rust index");
|
||||
let label_gcc_index =
|
||||
labels.iter().position(|&l| l == label).expect("wrong rust index");
|
||||
let gcc_index = label_gcc_index + outputs.len() + inputs.len();
|
||||
push_to_template(Some('l'), gcc_index);
|
||||
}
|
||||
|
|
@ -695,10 +694,12 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
|
|||
fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegClass) -> Type<'gcc> {
|
||||
match reg {
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => unimplemented!(),
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
|
||||
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
|
||||
unimplemented!()
|
||||
cx.type_vector(cx.type_i64(), 2)
|
||||
}
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
|
||||
|
|
@ -709,21 +710,13 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
|
|||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg)
|
||||
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
|
||||
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
|
||||
unimplemented!()
|
||||
cx.type_vector(cx.type_i64(), 2)
|
||||
}
|
||||
InlineAsmRegClass::Avr(_) => unimplemented!(),
|
||||
InlineAsmRegClass::Bpf(_) => unimplemented!(),
|
||||
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
|
||||
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!(),
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(),
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(),
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(),
|
||||
|
|
@ -736,26 +729,43 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
|
|||
}
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => cx.type_f32(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::mmx_reg) => unimplemented!(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) => unimplemented!(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => cx.type_i16(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::tmm_reg) => unimplemented!(),
|
||||
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
|
||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||
bug!("LLVM backend does not support SPIR-V")
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::mmx_reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::tmm_reg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
|
||||
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
|
||||
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => cx.type_i8(),
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => cx.type_i8(),
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(),
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(),
|
||||
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(),
|
||||
InlineAsmRegClass::S390x(
|
||||
S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr,
|
||||
) => cx.type_i32(),
|
||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
|
||||
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
|
||||
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!("GCC backend does not support SPIR-V")
|
||||
}
|
||||
InlineAsmRegClass::Err => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
let mut function_features = function_features
|
||||
.iter()
|
||||
.flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter())
|
||||
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
|
||||
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match *x {
|
||||
InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO(antoyo): support removing feature.
|
||||
InstructionSetAttr::ArmT32 => "thumb-mode",
|
||||
}))
|
||||
|
|
@ -118,8 +118,8 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
|
||||
if feature.starts_with('-') {
|
||||
Some(format!("no{}", feature))
|
||||
} else if feature.starts_with('+') {
|
||||
Some(feature[1..].to_string())
|
||||
} else if let Some(stripped) = feature.strip_prefix('+') {
|
||||
Some(stripped.to_string())
|
||||
} else {
|
||||
Some(feature.to_string())
|
||||
}
|
||||
|
|
@ -128,6 +128,12 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
.join(",");
|
||||
if !target_features.is_empty() {
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Target(&target_features));
|
||||
match cx.sess().target.arch.as_ref() {
|
||||
"x86" | "x86_64" | "powerpc" => {
|
||||
func.add_attribute(FnAttribute::Target(&target_features))
|
||||
}
|
||||
// The target attribute is not supported on other targets in GCC.
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,8 +130,7 @@ fn prepare_lto(
|
|||
}
|
||||
|
||||
let archive_data = unsafe {
|
||||
Mmap::map(File::open(&path).expect("couldn't open rlib"))
|
||||
.expect("couldn't map rlib")
|
||||
Mmap::map(File::open(path).expect("couldn't open rlib")).expect("couldn't map rlib")
|
||||
};
|
||||
let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib");
|
||||
let obj_files = archive
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ pub(crate) unsafe fn codegen(
|
|||
// FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by
|
||||
// transmuting an rvalue to an lvalue.
|
||||
// Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue
|
||||
context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name));
|
||||
context.dump_reproducer_to_file(format!("/tmp/reproducers/{}.c", module.name));
|
||||
println!("Dumped reproducer {}", module.name);
|
||||
}
|
||||
if env::var("CG_GCCJIT_DUMP_TO_FILE").as_deref() == Ok("1") {
|
||||
|
|
|
|||
23
src/base.rs
23
src/base.rs
|
|
@ -3,7 +3,7 @@ use std::env;
|
|||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
use gccjit::{FunctionType, GlobalKind};
|
||||
use gccjit::{CType, FunctionType, GlobalKind};
|
||||
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
||||
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
||||
use rustc_codegen_ssa::traits::DebugInfoMethods;
|
||||
|
|
@ -136,7 +136,7 @@ pub fn compile_codegen_unit(
|
|||
|
||||
let target_cpu = gcc_util::target_cpu(tcx.sess);
|
||||
if target_cpu != "generic" {
|
||||
context.add_command_line_option(&format!("-march={}", target_cpu));
|
||||
context.add_command_line_option(format!("-march={}", target_cpu));
|
||||
}
|
||||
|
||||
if tcx
|
||||
|
|
@ -182,7 +182,24 @@ pub fn compile_codegen_unit(
|
|||
context.set_allow_unreachable_blocks(true);
|
||||
|
||||
{
|
||||
let cx = CodegenCx::new(&context, cgu, tcx, target_info.supports_128bit_int());
|
||||
// TODO: to make it less error-prone (calling get_target_info() will add the flag
|
||||
// -fsyntax-only), forbid the compilation when get_target_info() is called on a
|
||||
// context.
|
||||
let f16_type_supported = target_info.supports_target_dependent_type(CType::Float16);
|
||||
let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32);
|
||||
let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64);
|
||||
let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128);
|
||||
// TODO: improve this to avoid passing that many arguments.
|
||||
let cx = CodegenCx::new(
|
||||
&context,
|
||||
cgu,
|
||||
tcx,
|
||||
target_info.supports_128bit_int(),
|
||||
f16_type_supported,
|
||||
f32_type_supported,
|
||||
f64_type_supported,
|
||||
f128_type_supported,
|
||||
);
|
||||
|
||||
let mono_items = cgu.items_in_deterministic_order(tcx);
|
||||
for &(mono_item, data) in &mono_items {
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
let mut on_stack_param_indices = FxHashSet::default();
|
||||
if let Some(indices) = self.on_stack_params.borrow().get(&gcc_func) {
|
||||
on_stack_param_indices = indices.clone();
|
||||
on_stack_param_indices.clone_from(indices);
|
||||
}
|
||||
|
||||
if all_args_match {
|
||||
|
|
@ -270,8 +270,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
} else {
|
||||
assert!(
|
||||
!((actual_ty.is_vector() && !expected_ty.is_vector())
|
||||
|| (!actual_ty.is_vector() && expected_ty.is_vector())),
|
||||
(!expected_ty.is_vector() || actual_ty.is_vector())
|
||||
&& (expected_ty.is_vector() || !actual_ty.is_vector()),
|
||||
"{:?} ({}) -> {:?} ({}), index: {:?}[{}]",
|
||||
actual_ty,
|
||||
actual_ty.is_vector(),
|
||||
|
|
@ -291,8 +291,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
.collect();
|
||||
|
||||
// NOTE: to take into account variadic functions.
|
||||
for i in casted_args.len()..args.len() {
|
||||
casted_args.push(args[i]);
|
||||
for arg in args.iter().skip(casted_args.len()) {
|
||||
casted_args.push(*arg);
|
||||
}
|
||||
|
||||
Cow::Owned(casted_args)
|
||||
|
|
@ -367,7 +367,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let function_address_names = self.function_address_names.borrow();
|
||||
let original_function_name = function_address_names.get(&func_ptr);
|
||||
llvm::adjust_intrinsic_arguments(
|
||||
&self,
|
||||
self,
|
||||
gcc_func,
|
||||
args.into(),
|
||||
&func_name,
|
||||
|
|
@ -375,7 +375,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
)
|
||||
};
|
||||
let args_adjusted = args.len() != previous_arg_count;
|
||||
let args = self.check_ptr_call("call", func_ptr, &*args);
|
||||
let args = self.check_ptr_call("call", func_ptr, &args);
|
||||
|
||||
// gccjit requires to use the result of functions, even when it's not used.
|
||||
// That's why we assign the result to a local or call add_eval().
|
||||
|
|
@ -387,7 +387,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
unsafe { RETURN_VALUE_COUNT += 1 };
|
||||
let return_value = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args);
|
||||
let return_value = llvm::adjust_intrinsic_return_value(
|
||||
&self,
|
||||
self,
|
||||
return_value,
|
||||
&func_name,
|
||||
&args,
|
||||
|
|
@ -455,7 +455,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
self.block.add_assignment(
|
||||
self.location,
|
||||
result,
|
||||
self.cx.context.new_call(self.location, func, &args),
|
||||
self.cx.context.new_call(self.location, func, args),
|
||||
);
|
||||
result.to_rvalue()
|
||||
}
|
||||
|
|
@ -610,7 +610,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
) -> RValue<'gcc> {
|
||||
let try_block = self.current_func().new_block("try");
|
||||
|
||||
let current_block = self.block.clone();
|
||||
let current_block = self.block;
|
||||
self.block = try_block;
|
||||
let call = self.call(typ, fn_attrs, None, func, args, None, instance); // TODO(antoyo): use funclet here?
|
||||
self.block = current_block;
|
||||
|
|
@ -764,6 +764,24 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
// FIXME(antoyo): this seems to produce the wrong result.
|
||||
return self.context.new_call(self.location, fmodf, &[a, b]);
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
match self.cx.type_kind(a_type) {
|
||||
TypeKind::Half | TypeKind::Float => {
|
||||
let fmodf = self.context.get_builtin_function("fmodf");
|
||||
return self.context.new_call(self.location, fmodf, &[a, b]);
|
||||
}
|
||||
TypeKind::Double => {
|
||||
let fmod = self.context.get_builtin_function("fmod");
|
||||
return self.context.new_call(self.location, fmod, &[a, b]);
|
||||
}
|
||||
TypeKind::FP128 => {
|
||||
let fmodl = self.context.get_builtin_function("fmodl");
|
||||
return self.context.new_call(self.location, fmodl, &[a, b]);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if let Some(vector_type) = a_type_unqualified.dyncast_vector() {
|
||||
assert_eq!(a_type_unqualified, b.get_type().unqualified());
|
||||
|
||||
|
|
@ -1136,7 +1154,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
// the following cast is required to avoid this error:
|
||||
// gcc_jit_context_new_call: mismatching types for argument 2 of function "__atomic_store_4": assignment to param arg1 (type: int) from loadedValue3577 (type: unsigned int __attribute__((aligned(4))))
|
||||
let int_type = atomic_store.get_param(1).to_rvalue().get_type();
|
||||
let value = self.context.new_cast(self.location, value, int_type);
|
||||
let value = self.context.new_bitcast(self.location, value, int_type);
|
||||
self.llbb().add_eval(
|
||||
self.location,
|
||||
self.context.new_call(self.location, atomic_store, &[ptr, value, ordering]),
|
||||
|
|
@ -1183,7 +1201,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
// NOTE: due to opaque pointers now being used, we need to cast here.
|
||||
let ptr = self.context.new_cast(self.location, ptr, typ.make_pointer());
|
||||
// NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified).
|
||||
let mut indices = indices.into_iter();
|
||||
let mut indices = indices.iter();
|
||||
let index = indices.next().expect("first index in inbounds_gep");
|
||||
let mut result = self.context.new_array_access(self.location, ptr, *index);
|
||||
for index in indices {
|
||||
|
|
@ -1687,6 +1705,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
// FIXME(antoyo): this does not zero-extend.
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
if value.get_type().is_bool() && dest_typ.is_i8(self.cx) {
|
||||
// FIXME(antoyo): hack because base::from_immediate converts i1 to i8.
|
||||
// Fix the code in codegen_ssa::base::from_immediate.
|
||||
return value;
|
||||
}
|
||||
>>>>>>> master
|
||||
self.gcc_int_cast(value, dest_typ)
|
||||
}
|
||||
|
||||
|
|
@ -2055,7 +2081,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
self.context.new_rvalue_from_vector(self.location, mask_type, &vector_elements);
|
||||
let shifted = self.context.new_rvalue_vector_perm(self.location, res, res, mask);
|
||||
shift *= 2;
|
||||
res = op(res, shifted, &self.context);
|
||||
res = op(res, shifted, self.context);
|
||||
}
|
||||
self.context
|
||||
.new_vector_access(self.location, res, self.context.new_rvalue_zero(self.int_type))
|
||||
|
|
@ -2071,7 +2097,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn vector_reduce_op(&mut self, src: RValue<'gcc>, op: BinaryOp) -> RValue<'gcc> {
|
||||
let loc = self.location.clone();
|
||||
let loc = self.location;
|
||||
self.vector_reduce(src, |a, b, context| context.new_binary_op(loc, op, a.get_type(), a, b))
|
||||
}
|
||||
|
||||
|
|
@ -2088,7 +2114,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
|
||||
let element_count = vector_type.get_num_units();
|
||||
(0..element_count)
|
||||
.into_iter()
|
||||
.map(|i| {
|
||||
self.context
|
||||
.new_vector_access(
|
||||
|
|
@ -2119,7 +2144,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
|
||||
let element_count = vector_type.get_num_units();
|
||||
(0..element_count)
|
||||
.into_iter()
|
||||
.map(|i| {
|
||||
self.context
|
||||
.new_vector_access(
|
||||
|
|
@ -2139,7 +2163,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
// Inspired by Hacker's Delight min implementation.
|
||||
pub fn vector_reduce_min(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let loc = self.location.clone();
|
||||
let loc = self.location;
|
||||
self.vector_reduce(src, |a, b, context| {
|
||||
let differences_or_zeros = difference_or_zero(loc, a, b, context);
|
||||
context.new_binary_op(loc, BinaryOp::Plus, b.get_type(), b, differences_or_zeros)
|
||||
|
|
@ -2148,7 +2172,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
// Inspired by Hacker's Delight max implementation.
|
||||
pub fn vector_reduce_max(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let loc = self.location.clone();
|
||||
let loc = self.location;
|
||||
self.vector_reduce(src, |a, b, context| {
|
||||
let differences_or_zeros = difference_or_zero(loc, a, b, context);
|
||||
context.new_binary_op(loc, BinaryOp::Minus, a.get_type(), a, differences_or_zeros)
|
||||
|
|
@ -2343,7 +2367,7 @@ impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
|
|||
|
||||
impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> {
|
||||
fn target_spec(&self) -> &Target {
|
||||
&self.cx.target_spec()
|
||||
self.cx.target_spec()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
|||
|
||||
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
|
||||
let func = if let Some(_func) = cx.get_declared_value(&sym) {
|
||||
let func = if let Some(_func) = cx.get_declared_value(sym) {
|
||||
// FIXME(antoyo): we never reach this because get_declared_value only returns global variables
|
||||
// and here we try to get a function.
|
||||
unreachable!();
|
||||
|
|
@ -68,7 +68,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
|||
}*/
|
||||
} else {
|
||||
cx.linkage.set(FunctionType::Extern);
|
||||
let func = cx.declare_fn(&sym, &fn_abi);
|
||||
let func = cx.declare_fn(sym, fn_abi);
|
||||
|
||||
attributes::from_fn_attrs(cx, func, instance);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
|
||||
fn global_string(&self, string: &str) -> LValue<'gcc> {
|
||||
// TODO(antoyo): handle non-null-terminated strings.
|
||||
let string = self.context.new_string_literal(&*string);
|
||||
let string = self.context.new_string_literal(string);
|
||||
let sym = self.generate_local_symbol_name("str");
|
||||
let global = self.declare_private_global(&sym, self.val_ty(string));
|
||||
global.global_set_initializer_rvalue(string);
|
||||
|
|
@ -187,7 +187,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
return self
|
||||
.context
|
||||
.new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
|
||||
} else if ty == self.double_type {
|
||||
}
|
||||
if ty == self.double_type {
|
||||
return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64));
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +298,7 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
|
|||
} else if self.is_ulonglong(cx) {
|
||||
cx.longlong_type
|
||||
} else {
|
||||
self.clone()
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +324,7 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
|
|||
} else if self.is_longlong(cx) {
|
||||
cx.ulonglong_type
|
||||
} else {
|
||||
self.clone()
|
||||
*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -436,7 +437,7 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> {
|
|||
}
|
||||
|
||||
fn is_vector(&self) -> bool {
|
||||
let mut typ = self.clone();
|
||||
let mut typ = *self;
|
||||
loop {
|
||||
if typ.dyncast_vector().is_some() {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -382,11 +382,8 @@ fn check_and_apply_linkage<'gcc, 'tcx>(
|
|||
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
|
||||
if let Some(linkage) = attrs.import_linkage {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
let global1 = cx.declare_global_with_linkage(
|
||||
&sym,
|
||||
cx.type_i8(),
|
||||
base::global_linkage_to_gcc(linkage),
|
||||
);
|
||||
let global1 =
|
||||
cx.declare_global_with_linkage(sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
|
||||
|
||||
// Declare an internal global `extern_with_linkage_foo` which
|
||||
// is initialized with the address of `foo`. If `foo` is
|
||||
|
|
@ -395,7 +392,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>(
|
|||
// `extern_with_linkage_foo` will instead be initialized to
|
||||
// zero.
|
||||
let mut real_name = "_rust_extern_with_linkage_".to_string();
|
||||
real_name.push_str(&sym);
|
||||
real_name.push_str(sym);
|
||||
let global2 = cx.define_global(&real_name, gcc_type, is_tls, attrs.link_section);
|
||||
// TODO(antoyo): set linkage.
|
||||
let value = cx.const_ptrcast(global1.get_address(None), gcc_type);
|
||||
|
|
@ -412,6 +409,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>(
|
|||
// don't do this then linker errors can be generated where the linker
|
||||
// complains that one object files has a thread local version of the
|
||||
// symbol and another one doesn't.
|
||||
cx.declare_global(&sym, gcc_type, GlobalKind::Imported, is_tls, attrs.link_section)
|
||||
cx.declare_global(sym, gcc_type, GlobalKind::Imported, is_tls, attrs.link_section)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
|||
pub sizet_type: Type<'gcc>,
|
||||
|
||||
pub supports_128bit_integers: bool,
|
||||
pub supports_f16_type: bool,
|
||||
pub supports_f32_type: bool,
|
||||
pub supports_f64_type: bool,
|
||||
pub supports_f128_type: bool,
|
||||
|
||||
pub float_type: Type<'gcc>,
|
||||
pub double_type: Type<'gcc>,
|
||||
|
|
@ -127,11 +131,16 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
context: &'gcc Context<'gcc>,
|
||||
codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
supports_128bit_integers: bool,
|
||||
supports_f16_type: bool,
|
||||
supports_f32_type: bool,
|
||||
supports_f64_type: bool,
|
||||
supports_f128_type: bool,
|
||||
) -> Self {
|
||||
let create_type = |ctype, rust_type| {
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
|
||||
|
|
@ -304,6 +313,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
sizet_type,
|
||||
|
||||
supports_128bit_integers,
|
||||
supports_f16_type,
|
||||
supports_f32_type,
|
||||
supports_f64_type,
|
||||
supports_f128_type,
|
||||
|
||||
float_type,
|
||||
double_type,
|
||||
|
|
@ -385,7 +398,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn sess(&self) -> &'tcx Session {
|
||||
&self.tcx.sess
|
||||
self.tcx.sess
|
||||
}
|
||||
|
||||
pub fn bitcast_if_needed(
|
||||
|
|
@ -432,7 +445,9 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
let func_name = self.tcx.symbol_name(instance).name;
|
||||
|
||||
let func = if self.intrinsics.borrow().contains_key(func_name) {
|
||||
self.intrinsics.borrow()[func_name].clone()
|
||||
self.intrinsics.borrow()[func_name]
|
||||
} else if let Some(variable) = self.get_declared_value(func_name) {
|
||||
return variable;
|
||||
} else {
|
||||
get_fn(self, instance)
|
||||
};
|
||||
|
|
@ -484,7 +499,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
let symbol_name = tcx.symbol_name(instance).name;
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
self.linkage.set(FunctionType::Extern);
|
||||
let func = self.declare_fn(symbol_name, &fn_abi);
|
||||
let func = self.declare_fn(symbol_name, fn_abi);
|
||||
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
|
||||
func
|
||||
}
|
||||
|
|
@ -504,7 +519,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
fn sess(&self) -> &Session {
|
||||
&self.tcx.sess
|
||||
self.tcx.sess
|
||||
}
|
||||
|
||||
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
|
||||
|
|
@ -521,7 +536,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
|
||||
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
|
||||
let entry_name = self.sess().target.entry_name.as_ref();
|
||||
if self.get_declared_value(entry_name).is_none() {
|
||||
if !self.functions.borrow().contains_key(entry_name) {
|
||||
Some(self.declare_entry_fn(entry_name, fn_type, ()))
|
||||
} else {
|
||||
// If the symbol already exists, it is an error: for example, the user wrote
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ fn compute_mir_scopes<'gcc, 'tcx>(
|
|||
/// FIXME(tempdragon/?): Add Scope Support Here.
|
||||
fn make_mir_scope<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
_instance: Instance<'tcx>,
|
||||
mir: &Body<'tcx>,
|
||||
variables: &Option<BitSet<SourceScope>>,
|
||||
debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>,
|
||||
|
|
@ -103,7 +103,7 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
|
||||
let scope_data = &mir.source_scopes[scope];
|
||||
let parent_scope = if let Some(parent) = scope_data.parent_scope {
|
||||
make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent);
|
||||
make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent);
|
||||
debug_context.scopes[parent]
|
||||
} else {
|
||||
// The root is the function itself.
|
||||
|
|
@ -117,7 +117,7 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
return;
|
||||
};
|
||||
|
||||
if let Some(vars) = variables {
|
||||
if let Some(ref vars) = *variables {
|
||||
if !vars.contains(scope) && scope_data.inlined.is_none() {
|
||||
// Do not create a DIScope if there are no variables defined in this
|
||||
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
|
||||
|
|
@ -135,8 +135,14 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
|
||||
// FIXME(eddyb) this doesn't account for the macro-related
|
||||
// `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
|
||||
let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
|
||||
cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span)
|
||||
|
||||
// TODO(tempdragon): Add scope support and then revert to cg_llvm version of this closure
|
||||
// NOTE: These variables passed () here.
|
||||
// Changed to comply to clippy.
|
||||
|
||||
/* let callsite_scope = */
|
||||
parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
|
||||
cx.dbg_loc(/* callsite_scope */ (), parent_scope.inlined_at, callsite_span)
|
||||
});
|
||||
let p_inlined_at = parent_scope.inlined_at;
|
||||
// TODO(tempdragon): dbg_scope: Add support for scope extension here.
|
||||
|
|
@ -224,7 +230,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
file_end_pos: BytePos(0),
|
||||
};
|
||||
let mut fn_debug_context = FunctionDebugContext {
|
||||
scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes.as_slice()),
|
||||
scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()),
|
||||
inlined_function_scopes: Default::default(),
|
||||
};
|
||||
|
||||
|
|
@ -273,16 +279,19 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
) -> Self::DILocation {
|
||||
let pos = span.lo();
|
||||
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
|
||||
let loc = match &file.name {
|
||||
rustc_span::FileName::Real(name) => match name {
|
||||
rustc_span::RealFileName::LocalPath(name) => {
|
||||
let loc = match file.name {
|
||||
rustc_span::FileName::Real(ref name) => match *name {
|
||||
rustc_span::RealFileName::LocalPath(ref name) => {
|
||||
if let Some(name) = name.to_str() {
|
||||
self.context.new_location(name, line as i32, col as i32)
|
||||
} else {
|
||||
Location::null()
|
||||
}
|
||||
}
|
||||
rustc_span::RealFileName::Remapped { local_path, virtual_name: _ } => {
|
||||
rustc_span::RealFileName::Remapped {
|
||||
ref local_path,
|
||||
virtual_name: ref _unused,
|
||||
} => {
|
||||
if let Some(name) = local_path.as_ref() {
|
||||
if let Some(name) = name.to_str() {
|
||||
self.context.new_location(name, line as i32, col as i32)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
|
||||
pub fn declare_unnamed_global(&self, ty: Type<'gcc>) -> LValue<'gcc> {
|
||||
let name = self.generate_local_symbol_name("global");
|
||||
self.context.new_global(None, GlobalKind::Internal, ty, &name)
|
||||
self.context.new_global(None, GlobalKind::Internal, ty, name)
|
||||
}
|
||||
|
||||
pub fn declare_global_with_linkage(
|
||||
|
|
@ -176,16 +176,14 @@ fn declare_raw_fn<'gcc>(
|
|||
cx.functions.borrow()[name]
|
||||
} else {
|
||||
let params: Vec<_> = param_types
|
||||
.into_iter()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, param)| {
|
||||
cx.context.new_parameter(None, *param, &format!("param{}", index))
|
||||
}) // TODO(antoyo): set name.
|
||||
.map(|(index, param)| cx.context.new_parameter(None, *param, format!("param{}", index))) // TODO(antoyo): set name.
|
||||
.collect();
|
||||
#[cfg(not(feature = "master"))]
|
||||
let name = mangle_name(name);
|
||||
let name = &mangle_name(name);
|
||||
let func =
|
||||
cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, &name, variadic);
|
||||
cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, name, variadic);
|
||||
cx.functions.borrow_mut().insert(name.to_string(), func);
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
|
|
@ -200,10 +198,10 @@ fn declare_raw_fn<'gcc>(
|
|||
// create a wrapper function that calls rust_eh_personality.
|
||||
|
||||
let params: Vec<_> = param_types
|
||||
.into_iter()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, param)| {
|
||||
cx.context.new_parameter(None, *param, &format!("param{}", index))
|
||||
cx.context.new_parameter(None, *param, format!("param{}", index))
|
||||
}) // TODO(antoyo): set name.
|
||||
.collect();
|
||||
let gcc_func = cx.context.new_function(
|
||||
|
|
|
|||
58
src/int.rs
58
src/int.rs
|
|
@ -2,8 +2,6 @@
|
|||
//! This module exists because some integer types are not supported on some gcc platforms, e.g.
|
||||
//! 128-bit integers on 32-bit platforms and thus require to be handled manually.
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
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};
|
||||
|
|
@ -40,7 +38,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
self.cx.context.new_unary_op(self.location, operation, typ, a)
|
||||
} else {
|
||||
let element_type = typ.dyncast_array().expect("element type");
|
||||
self.from_low_high_rvalues(
|
||||
self.concat_low_high_rvalues(
|
||||
typ,
|
||||
self.cx.context.new_unary_op(
|
||||
self.location,
|
||||
|
|
@ -126,7 +124,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let shift_value = self.gcc_sub(b, sixty_four);
|
||||
let high = self.high(a);
|
||||
let sign = if a_type.is_signed(self) { high >> sixty_three } else { zero };
|
||||
let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign);
|
||||
let array_value = self.concat_low_high_rvalues(a_type, high >> shift_value, sign);
|
||||
then_block.add_assignment(self.location, result, array_value);
|
||||
then_block.end_with_jump(self.location, after_block);
|
||||
|
||||
|
|
@ -138,12 +136,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
let shift_value = self.gcc_sub(sixty_four, b);
|
||||
// NOTE: cast low to its unsigned type in order to perform a logical right shift.
|
||||
let unsigned_type = native_int_type.to_unsigned(&self.cx);
|
||||
let unsigned_type = native_int_type.to_unsigned(self.cx);
|
||||
let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type);
|
||||
let shifted_low = casted_low >> self.context.new_cast(self.location, b, unsigned_type);
|
||||
let shifted_low = self.context.new_cast(self.location, shifted_low, native_int_type);
|
||||
let array_value =
|
||||
self.from_low_high_rvalues(a_type, (high << shift_value) | shifted_low, high >> b);
|
||||
let array_value = self.concat_low_high_rvalues(
|
||||
a_type,
|
||||
(high << shift_value) | shifted_low,
|
||||
high >> b,
|
||||
);
|
||||
actual_else_block.add_assignment(self.location, result, array_value);
|
||||
actual_else_block.end_with_jump(self.location, after_block);
|
||||
|
||||
|
|
@ -267,10 +268,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) {
|
||||
use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*};
|
||||
|
||||
let new_kind = match typ.kind() {
|
||||
let new_kind = match *typ.kind() {
|
||||
Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
|
||||
Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
|
||||
t @ (Uint(_) | Int(_)) => t.clone(),
|
||||
t @ (Uint(_) | Int(_)) => t,
|
||||
_ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
|
||||
};
|
||||
|
||||
|
|
@ -356,7 +357,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
let intrinsic = self.context.get_builtin_function(&name);
|
||||
let intrinsic = self.context.get_builtin_function(name);
|
||||
let res = self
|
||||
.current_func()
|
||||
// TODO(antoyo): is it correct to use rhs type instead of the parameter typ?
|
||||
|
|
@ -466,7 +467,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let native_int_type = a_type.dyncast_array().expect("get element type");
|
||||
// NOTE: cast low to its unsigned type in order to perform a comparison correctly (e.g.
|
||||
// the sign is only on high).
|
||||
let unsigned_type = native_int_type.to_unsigned(&self.cx);
|
||||
let unsigned_type = native_int_type.to_unsigned(self.cx);
|
||||
|
||||
let lhs_low = self.context.new_cast(self.location, self.low(lhs), unsigned_type);
|
||||
let rhs_low = self.context.new_cast(self.location, self.low(rhs), unsigned_type);
|
||||
|
|
@ -601,7 +602,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
| IntPredicate::IntULT
|
||||
| IntPredicate::IntULE => {
|
||||
if !a_type.is_vector() {
|
||||
let unsigned_type = a_type.to_unsigned(&self.cx);
|
||||
let unsigned_type = a_type.to_unsigned(self.cx);
|
||||
lhs = self.context.new_cast(self.location, lhs, unsigned_type);
|
||||
rhs = self.context.new_cast(self.location, rhs, unsigned_type);
|
||||
}
|
||||
|
|
@ -624,7 +625,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
{
|
||||
a ^ b
|
||||
} else {
|
||||
self.from_low_high_rvalues(
|
||||
self.concat_low_high_rvalues(
|
||||
a_type,
|
||||
self.low(a) ^ self.low(b),
|
||||
self.high(a) ^ self.high(b),
|
||||
|
|
@ -685,7 +686,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
self.llbb().end_with_conditional(self.location, condition, then_block, else_block);
|
||||
|
||||
let array_value =
|
||||
self.from_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four));
|
||||
self.concat_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four));
|
||||
then_block.add_assignment(self.location, result, array_value);
|
||||
then_block.end_with_jump(self.location, after_block);
|
||||
|
||||
|
|
@ -697,13 +698,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
// NOTE: cast low to its unsigned type in order to perform a logical right shift.
|
||||
// TODO(antoyo): adjust this ^ comment.
|
||||
let unsigned_type = native_int_type.to_unsigned(&self.cx);
|
||||
let unsigned_type = native_int_type.to_unsigned(self.cx);
|
||||
let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type);
|
||||
let shift_value = self.context.new_cast(self.location, sixty_four - b, unsigned_type);
|
||||
let high_low =
|
||||
self.context.new_cast(self.location, casted_low >> shift_value, native_int_type);
|
||||
|
||||
let array_value = self.from_low_high_rvalues(
|
||||
let array_value = self.concat_low_high_rvalues(
|
||||
a_type,
|
||||
self.low(a) << b,
|
||||
(self.high(a) << b) | high_low,
|
||||
|
|
@ -732,7 +733,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
// NOTE: we also need to swap the two elements here, in addition to swapping inside
|
||||
// the elements themselves like done above.
|
||||
return self.from_low_high_rvalues(arg_type, swapped_msb, swapped_lsb);
|
||||
return self.concat_low_high_rvalues(arg_type, swapped_msb, swapped_lsb);
|
||||
}
|
||||
|
||||
// TODO(antoyo): check if it's faster to use string literals and a
|
||||
|
|
@ -751,10 +752,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
pub fn gcc_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
|
||||
if self.is_native_int_type_or_bool(typ) {
|
||||
self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from"))
|
||||
self.context.new_rvalue_from_long(typ, int)
|
||||
} else {
|
||||
// NOTE: set the sign in high.
|
||||
self.from_low_high(typ, int, -(int.is_negative() as i64))
|
||||
self.concat_low_high(typ, int, -(int.is_negative() as i64))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -764,10 +765,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let num = self.context.new_rvalue_from_long(self.u64_type, int as i64);
|
||||
self.gcc_int_cast(num, typ)
|
||||
} else if self.is_native_int_type_or_bool(typ) {
|
||||
self.context
|
||||
.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64)
|
||||
self.context.new_rvalue_from_long(typ, int as i64)
|
||||
} else {
|
||||
self.from_low_high(typ, int as i64, 0)
|
||||
self.concat_low_high(typ, int as i64, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -784,7 +784,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let shift = high << sixty_four;
|
||||
shift | self.context.new_cast(None, low, typ)
|
||||
} else {
|
||||
self.from_low_high(typ, low as i64, high as i64)
|
||||
self.concat_low_high(typ, low as i64, high as i64)
|
||||
}
|
||||
} else if typ.is_i128(self) {
|
||||
// FIXME(antoyo): libgccjit cannot create 128-bit values yet.
|
||||
|
|
@ -799,7 +799,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
if self.is_native_int_type_or_bool(typ) {
|
||||
self.context.new_rvalue_zero(typ)
|
||||
} else {
|
||||
self.from_low_high(typ, 0, 0)
|
||||
self.concat_low_high(typ, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -837,7 +837,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
"both types should either be native or non-native for or operation"
|
||||
);
|
||||
let native_int_type = a_type.dyncast_array().expect("get element type");
|
||||
self.from_low_high_rvalues(
|
||||
self.concat_low_high_rvalues(
|
||||
a_type,
|
||||
self.context.new_binary_op(
|
||||
loc,
|
||||
|
|
@ -882,7 +882,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let is_negative =
|
||||
self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
|
||||
let is_negative = self.gcc_int_cast(is_negative, dest_element_type);
|
||||
self.from_low_high_rvalues(
|
||||
self.concat_low_high_rvalues(
|
||||
dest_typ,
|
||||
self.context.new_cast(None, value, dest_element_type),
|
||||
self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative),
|
||||
|
|
@ -950,7 +950,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
return self.context.new_cast(None, value, dest_typ);
|
||||
}
|
||||
|
||||
debug_assert!(value_type.dyncast_array().is_some());
|
||||
debug_assert!(dest_typ.dyncast_array().is_some());
|
||||
let name_suffix = match self.type_kind(value_type) {
|
||||
TypeKind::Float => "sfti",
|
||||
TypeKind::Double => "dfti",
|
||||
|
|
@ -1002,7 +1002,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
.to_rvalue()
|
||||
}
|
||||
|
||||
fn from_low_high_rvalues(
|
||||
fn concat_low_high_rvalues(
|
||||
&self,
|
||||
typ: Type<'gcc>,
|
||||
low: RValue<'gcc>,
|
||||
|
|
@ -1017,7 +1017,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
self.context.new_array_constructor(None, typ, &values)
|
||||
}
|
||||
|
||||
fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
|
||||
fn concat_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
|
||||
let (first, last) = match self.sess().target.options.endian {
|
||||
Endian::Little => (low, high),
|
||||
Endian::Big => (high, low),
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ match name {
|
|||
"llvm.amdgcn.cvt.sr.bf8.f32" => "__builtin_amdgcn_cvt_sr_bf8_f32",
|
||||
"llvm.amdgcn.cvt.sr.fp8.f32" => "__builtin_amdgcn_cvt_sr_fp8_f32",
|
||||
"llvm.amdgcn.dispatch.id" => "__builtin_amdgcn_dispatch_id",
|
||||
"llvm.amdgcn.dot4.f32.bf8.bf8" => "__builtin_amdgcn_dot4_f32_bf8_bf8",
|
||||
"llvm.amdgcn.dot4.f32.bf8.fp8" => "__builtin_amdgcn_dot4_f32_bf8_fp8",
|
||||
"llvm.amdgcn.dot4.f32.fp8.bf8" => "__builtin_amdgcn_dot4_f32_fp8_bf8",
|
||||
"llvm.amdgcn.dot4.f32.fp8.fp8" => "__builtin_amdgcn_dot4_f32_fp8_fp8",
|
||||
"llvm.amdgcn.ds.add.gs.reg.rtn" => "__builtin_amdgcn_ds_add_gs_reg_rtn",
|
||||
"llvm.amdgcn.ds.bpermute" => "__builtin_amdgcn_ds_bpermute",
|
||||
"llvm.amdgcn.ds.fadd.v2bf16" => "__builtin_amdgcn_ds_atomic_fadd_v2bf16",
|
||||
|
|
@ -2291,6 +2295,10 @@ match name {
|
|||
"llvm.loongarch.csrxchg.d" => "__builtin_loongarch_csrxchg_d",
|
||||
"llvm.loongarch.csrxchg.w" => "__builtin_loongarch_csrxchg_w",
|
||||
"llvm.loongarch.dbar" => "__builtin_loongarch_dbar",
|
||||
"llvm.loongarch.frecipe.d" => "__builtin_loongarch_frecipe_d",
|
||||
"llvm.loongarch.frecipe.s" => "__builtin_loongarch_frecipe_s",
|
||||
"llvm.loongarch.frsqrte.d" => "__builtin_loongarch_frsqrte_d",
|
||||
"llvm.loongarch.frsqrte.s" => "__builtin_loongarch_frsqrte_s",
|
||||
"llvm.loongarch.ibar" => "__builtin_loongarch_ibar",
|
||||
"llvm.loongarch.iocsrrd.b" => "__builtin_loongarch_iocsrrd_b",
|
||||
"llvm.loongarch.iocsrrd.d" => "__builtin_loongarch_iocsrrd_d",
|
||||
|
|
@ -2529,6 +2537,8 @@ match name {
|
|||
"llvm.loongarch.lasx.xvfnmsub.s" => "__builtin_lasx_xvfnmsub_s",
|
||||
"llvm.loongarch.lasx.xvfrecip.d" => "__builtin_lasx_xvfrecip_d",
|
||||
"llvm.loongarch.lasx.xvfrecip.s" => "__builtin_lasx_xvfrecip_s",
|
||||
"llvm.loongarch.lasx.xvfrecipe.d" => "__builtin_lasx_xvfrecipe_d",
|
||||
"llvm.loongarch.lasx.xvfrecipe.s" => "__builtin_lasx_xvfrecipe_s",
|
||||
"llvm.loongarch.lasx.xvfrint.d" => "__builtin_lasx_xvfrint_d",
|
||||
"llvm.loongarch.lasx.xvfrint.s" => "__builtin_lasx_xvfrint_s",
|
||||
"llvm.loongarch.lasx.xvfrintrm.d" => "__builtin_lasx_xvfrintrm_d",
|
||||
|
|
@ -2541,6 +2551,8 @@ match name {
|
|||
"llvm.loongarch.lasx.xvfrintrz.s" => "__builtin_lasx_xvfrintrz_s",
|
||||
"llvm.loongarch.lasx.xvfrsqrt.d" => "__builtin_lasx_xvfrsqrt_d",
|
||||
"llvm.loongarch.lasx.xvfrsqrt.s" => "__builtin_lasx_xvfrsqrt_s",
|
||||
"llvm.loongarch.lasx.xvfrsqrte.d" => "__builtin_lasx_xvfrsqrte_d",
|
||||
"llvm.loongarch.lasx.xvfrsqrte.s" => "__builtin_lasx_xvfrsqrte_s",
|
||||
"llvm.loongarch.lasx.xvfrstp.b" => "__builtin_lasx_xvfrstp_b",
|
||||
"llvm.loongarch.lasx.xvfrstp.h" => "__builtin_lasx_xvfrstp_h",
|
||||
"llvm.loongarch.lasx.xvfrstpi.b" => "__builtin_lasx_xvfrstpi_b",
|
||||
|
|
@ -3255,6 +3267,8 @@ match name {
|
|||
"llvm.loongarch.lsx.vfnmsub.s" => "__builtin_lsx_vfnmsub_s",
|
||||
"llvm.loongarch.lsx.vfrecip.d" => "__builtin_lsx_vfrecip_d",
|
||||
"llvm.loongarch.lsx.vfrecip.s" => "__builtin_lsx_vfrecip_s",
|
||||
"llvm.loongarch.lsx.vfrecipe.d" => "__builtin_lsx_vfrecipe_d",
|
||||
"llvm.loongarch.lsx.vfrecipe.s" => "__builtin_lsx_vfrecipe_s",
|
||||
"llvm.loongarch.lsx.vfrint.d" => "__builtin_lsx_vfrint_d",
|
||||
"llvm.loongarch.lsx.vfrint.s" => "__builtin_lsx_vfrint_s",
|
||||
"llvm.loongarch.lsx.vfrintrm.d" => "__builtin_lsx_vfrintrm_d",
|
||||
|
|
@ -3267,6 +3281,8 @@ match name {
|
|||
"llvm.loongarch.lsx.vfrintrz.s" => "__builtin_lsx_vfrintrz_s",
|
||||
"llvm.loongarch.lsx.vfrsqrt.d" => "__builtin_lsx_vfrsqrt_d",
|
||||
"llvm.loongarch.lsx.vfrsqrt.s" => "__builtin_lsx_vfrsqrt_s",
|
||||
"llvm.loongarch.lsx.vfrsqrte.d" => "__builtin_lsx_vfrsqrte_d",
|
||||
"llvm.loongarch.lsx.vfrsqrte.s" => "__builtin_lsx_vfrsqrte_s",
|
||||
"llvm.loongarch.lsx.vfrstp.b" => "__builtin_lsx_vfrstp_b",
|
||||
"llvm.loongarch.lsx.vfrstp.h" => "__builtin_lsx_vfrstp_h",
|
||||
"llvm.loongarch.lsx.vfrstpi.b" => "__builtin_lsx_vfrstpi_b",
|
||||
|
|
@ -4434,6 +4450,7 @@ match name {
|
|||
"llvm.nvvm.abs.bf16x2" => "__nvvm_abs_bf16x2",
|
||||
"llvm.nvvm.abs.i" => "__nvvm_abs_i",
|
||||
"llvm.nvvm.abs.ll" => "__nvvm_abs_ll",
|
||||
"llvm.nvvm.activemask" => "__nvvm_activemask",
|
||||
"llvm.nvvm.add.rm.d" => "__nvvm_add_rm_d",
|
||||
"llvm.nvvm.add.rm.f" => "__nvvm_add_rm_f",
|
||||
"llvm.nvvm.add.rm.ftz.f" => "__nvvm_add_rm_ftz_f",
|
||||
|
|
@ -4522,6 +4539,7 @@ match name {
|
|||
"llvm.nvvm.ex2.approx.d" => "__nvvm_ex2_approx_d",
|
||||
"llvm.nvvm.ex2.approx.f" => "__nvvm_ex2_approx_f",
|
||||
"llvm.nvvm.ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f",
|
||||
"llvm.nvvm.exit" => "__nvvm_exit",
|
||||
"llvm.nvvm.f2bf16.rn" => "__nvvm_f2bf16_rn",
|
||||
"llvm.nvvm.f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu",
|
||||
"llvm.nvvm.f2bf16.rz" => "__nvvm_f2bf16_rz",
|
||||
|
|
@ -4722,8 +4740,11 @@ match name {
|
|||
"llvm.nvvm.mul24.ui" => "__nvvm_mul24_ui",
|
||||
"llvm.nvvm.mulhi.i" => "__nvvm_mulhi_i",
|
||||
"llvm.nvvm.mulhi.ll" => "__nvvm_mulhi_ll",
|
||||
"llvm.nvvm.mulhi.s" => "__nvvm_mulhi_s",
|
||||
"llvm.nvvm.mulhi.ui" => "__nvvm_mulhi_ui",
|
||||
"llvm.nvvm.mulhi.ull" => "__nvvm_mulhi_ull",
|
||||
"llvm.nvvm.mulhi.us" => "__nvvm_mulhi_us",
|
||||
"llvm.nvvm.nanosleep" => "__nvvm_nanosleep",
|
||||
"llvm.nvvm.neg.bf16" => "__nvvm_neg_bf16",
|
||||
"llvm.nvvm.neg.bf16x2" => "__nvvm_neg_bf16x2",
|
||||
"llvm.nvvm.popc.i" => "__nvvm_popc_i",
|
||||
|
|
@ -4783,6 +4804,7 @@ match name {
|
|||
"llvm.nvvm.read.ptx.sreg.envreg7" => "__nvvm_read_ptx_sreg_envreg7",
|
||||
"llvm.nvvm.read.ptx.sreg.envreg8" => "__nvvm_read_ptx_sreg_envreg8",
|
||||
"llvm.nvvm.read.ptx.sreg.envreg9" => "__nvvm_read_ptx_sreg_envreg9",
|
||||
"llvm.nvvm.read.ptx.sreg.globaltimer" => "__nvvm_read_ptx_sreg_globaltimer",
|
||||
"llvm.nvvm.read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_gridid",
|
||||
// [DUPLICATE]: "llvm.nvvm.read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_",
|
||||
"llvm.nvvm.read.ptx.sreg.laneid" => "__nvvm_read_ptx_sreg_laneid",
|
||||
|
|
@ -4835,6 +4857,7 @@ match name {
|
|||
"llvm.nvvm.redux.sync.umax" => "__nvvm_redux_sync_umax",
|
||||
"llvm.nvvm.redux.sync.umin" => "__nvvm_redux_sync_umin",
|
||||
"llvm.nvvm.redux.sync.xor" => "__nvvm_redux_sync_xor",
|
||||
"llvm.nvvm.reflect" => "__nvvm_reflect",
|
||||
"llvm.nvvm.rotate.b32" => "__nvvm_rotate_b32",
|
||||
"llvm.nvvm.rotate.b64" => "__nvvm_rotate_b64",
|
||||
"llvm.nvvm.rotate.right.b64" => "__nvvm_rotate_right_b64",
|
||||
|
|
@ -4845,7 +4868,11 @@ match name {
|
|||
"llvm.nvvm.rsqrt.approx.f" => "__nvvm_rsqrt_approx_f",
|
||||
"llvm.nvvm.rsqrt.approx.ftz.f" => "__nvvm_rsqrt_approx_ftz_f",
|
||||
"llvm.nvvm.sad.i" => "__nvvm_sad_i",
|
||||
"llvm.nvvm.sad.ll" => "__nvvm_sad_ll",
|
||||
"llvm.nvvm.sad.s" => "__nvvm_sad_s",
|
||||
"llvm.nvvm.sad.ui" => "__nvvm_sad_ui",
|
||||
"llvm.nvvm.sad.ull" => "__nvvm_sad_ull",
|
||||
"llvm.nvvm.sad.us" => "__nvvm_sad_us",
|
||||
"llvm.nvvm.saturate.d" => "__nvvm_saturate_d",
|
||||
"llvm.nvvm.saturate.f" => "__nvvm_saturate_f",
|
||||
"llvm.nvvm.saturate.ftz.f" => "__nvvm_saturate_ftz_f",
|
||||
|
|
@ -5471,6 +5498,7 @@ match name {
|
|||
"llvm.ppc.fctiwz" => "__builtin_ppc_fctiwz",
|
||||
"llvm.ppc.fctudz" => "__builtin_ppc_fctudz",
|
||||
"llvm.ppc.fctuwz" => "__builtin_ppc_fctuwz",
|
||||
"llvm.ppc.fence" => "__builtin_ppc_fence",
|
||||
"llvm.ppc.fmaf128.round.to.odd" => "__builtin_fmaf128_round_to_odd",
|
||||
"llvm.ppc.fmsub" => "__builtin_ppc_fmsub",
|
||||
"llvm.ppc.fmsubs" => "__builtin_ppc_fmsubs",
|
||||
|
|
@ -5599,6 +5627,9 @@ match name {
|
|||
"llvm.ppc.qpx.qvstfs" => "__builtin_qpx_qvstfs",
|
||||
"llvm.ppc.qpx.qvstfsa" => "__builtin_qpx_qvstfsa",
|
||||
"llvm.ppc.readflm" => "__builtin_readflm",
|
||||
"llvm.ppc.rldimi" => "__builtin_ppc_rldimi",
|
||||
"llvm.ppc.rlwimi" => "__builtin_ppc_rlwimi",
|
||||
"llvm.ppc.rlwnm" => "__builtin_ppc_rlwnm",
|
||||
"llvm.ppc.scalar.extract.expq" => "__builtin_vsx_scalar_extract_expq",
|
||||
"llvm.ppc.scalar.insert.exp.qp" => "__builtin_vsx_scalar_insert_exp_qp",
|
||||
"llvm.ppc.set.texasr" => "__builtin_set_texasr",
|
||||
|
|
@ -5912,6 +5943,8 @@ match name {
|
|||
"llvm.s390.vupllb" => "__builtin_s390_vupllb",
|
||||
"llvm.s390.vupllf" => "__builtin_s390_vupllf",
|
||||
"llvm.s390.vupllh" => "__builtin_s390_vupllh",
|
||||
// spv
|
||||
"llvm.spv.create.handle" => "__builtin_hlsl_create_handle",
|
||||
// ve
|
||||
"llvm.ve.vl.andm.MMM" => "__builtin_ve_vl_andm_MMM",
|
||||
"llvm.ve.vl.andm.mmm" => "__builtin_ve_vl_andm_mmm",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
|
|||
// Some LLVM intrinsics do not map 1-to-1 to GCC intrinsics, so we add the missing
|
||||
// arguments here.
|
||||
if gcc_func.get_param_count() != args.len() {
|
||||
match &*func_name {
|
||||
match func_name {
|
||||
// NOTE: the following intrinsics have a different number of parameters in LLVM and GCC.
|
||||
"__builtin_ia32_prold512_mask"
|
||||
| "__builtin_ia32_pmuldq512_mask"
|
||||
|
|
@ -380,7 +380,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
|
|||
_ => (),
|
||||
}
|
||||
} else {
|
||||
match &*func_name {
|
||||
match func_name {
|
||||
"__builtin_ia32_rndscaless_mask_round" | "__builtin_ia32_rndscalesd_mask_round" => {
|
||||
let new_args = args.to_vec();
|
||||
let arg3_type = gcc_func.get_param_type(2);
|
||||
|
|
@ -629,17 +629,22 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
|
|||
|
||||
#[cfg(feature = "master")]
|
||||
pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> {
|
||||
match name {
|
||||
let gcc_name = match name {
|
||||
"llvm.prefetch" => {
|
||||
let gcc_name = "__builtin_prefetch";
|
||||
let func = cx.context.get_builtin_function(gcc_name);
|
||||
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
|
||||
return func;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let gcc_name = match name {
|
||||
"llvm.aarch64.isb" => {
|
||||
// FIXME: GCC doesn't support __builtin_arm_isb yet, check if this builtin is OK.
|
||||
let gcc_name = "__atomic_thread_fence";
|
||||
let func = cx.context.get_builtin_function(gcc_name);
|
||||
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
|
||||
return func;
|
||||
}
|
||||
|
||||
"llvm.x86.xgetbv" => "__builtin_ia32_xgetbv",
|
||||
// NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html
|
||||
"llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd",
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
|
|||
sym::abort => "abort",
|
||||
_ => return None,
|
||||
};
|
||||
Some(cx.context.get_builtin_function(&gcc_name))
|
||||
Some(cx.context.get_builtin_function(gcc_name))
|
||||
}
|
||||
|
||||
impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
|
|
@ -122,6 +122,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
|
||||
|
||||
let simple = get_simple_intrinsic(self, name);
|
||||
|
||||
// FIXME(tempdragon): Re-enable `clippy::suspicious_else_formatting` if the following issue is solved:
|
||||
// https://github.com/rust-lang/rust-clippy/issues/12497
|
||||
// and leave `else if use_integer_compare` to be placed "as is".
|
||||
#[allow(clippy::suspicious_else_formatting)]
|
||||
let llval = match name {
|
||||
_ if simple.is_some() => {
|
||||
// FIXME(antoyo): remove this cast when the API supports function.
|
||||
|
|
@ -169,7 +174,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
let ptr = args[0].immediate();
|
||||
let load = if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
|
||||
let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode {
|
||||
let gcc_ty = ty.gcc_type(self);
|
||||
self.volatile_load(gcc_ty, ptr)
|
||||
} else {
|
||||
|
|
@ -388,7 +393,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
};
|
||||
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
|
||||
if let PassMode::Cast { cast: ref ty, .. } = fn_abi.ret.mode {
|
||||
let ptr_llty = self.type_ptr_to(ty.gcc_type(self));
|
||||
let ptr = self.pointercast(result.val.llval, ptr_llty);
|
||||
self.store(llval, ptr, result.val.align);
|
||||
|
|
@ -594,7 +599,7 @@ fn int_type_width_signed<'gcc, 'tcx>(
|
|||
ty: Ty<'tcx>,
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
) -> Option<(u64, bool)> {
|
||||
match ty.kind() {
|
||||
match *ty.kind() {
|
||||
ty::Int(t) => Some((
|
||||
match t {
|
||||
rustc_middle::ty::IntTy::Isize => u64::from(cx.tcx.sess.target.pointer_width),
|
||||
|
|
@ -707,13 +712,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let count_leading_zeroes =
|
||||
// TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here
|
||||
// instead of using is_uint().
|
||||
if arg_type.is_uint(&self.cx) {
|
||||
if arg_type.is_uint(self.cx) {
|
||||
"__builtin_clz"
|
||||
}
|
||||
else if arg_type.is_ulong(&self.cx) {
|
||||
else if arg_type.is_ulong(self.cx) {
|
||||
"__builtin_clzl"
|
||||
}
|
||||
else if arg_type.is_ulonglong(&self.cx) {
|
||||
else if arg_type.is_ulonglong(self.cx) {
|
||||
"__builtin_clzll"
|
||||
}
|
||||
else if width == 128 {
|
||||
|
|
@ -788,17 +793,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
let (count_trailing_zeroes, expected_type) =
|
||||
// TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here
|
||||
// instead of using is_uint().
|
||||
if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) {
|
||||
if arg_type.is_uchar(self.cx) || arg_type.is_ushort(self.cx) || arg_type.is_uint(self.cx) {
|
||||
// NOTE: we don't need to & 0xFF for uchar because the result is undefined on zero.
|
||||
("__builtin_ctz", self.cx.uint_type)
|
||||
}
|
||||
else if arg_type.is_ulong(&self.cx) {
|
||||
else if arg_type.is_ulong(self.cx) {
|
||||
("__builtin_ctzl", self.cx.ulong_type)
|
||||
}
|
||||
else if arg_type.is_ulonglong(&self.cx) {
|
||||
else if arg_type.is_ulonglong(self.cx) {
|
||||
("__builtin_ctzll", self.cx.ulonglong_type)
|
||||
}
|
||||
else if arg_type.is_u128(&self.cx) {
|
||||
else if arg_type.is_u128(self.cx) {
|
||||
// Adapted from the algorithm to count leading zeroes from: https://stackoverflow.com/a/28433850/389119
|
||||
let array_type = self.context.new_array_type(None, arg_type, 3);
|
||||
let result = self.current_func()
|
||||
|
|
@ -880,7 +885,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
// only break apart 128-bit ints if they're not natively supported
|
||||
// TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
|
||||
if value_type.is_u128(&self.cx) && !self.cx.supports_128bit_integers {
|
||||
if value_type.is_u128(self.cx) && !self.cx.supports_128bit_integers {
|
||||
let sixty_four = self.gcc_int(value_type, 64);
|
||||
let right_shift = self.gcc_lshr(value, sixty_four);
|
||||
let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
|
||||
|
|
@ -1003,7 +1008,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
// Return `result_type`'s maximum or minimum value on overflow
|
||||
// NOTE: convert the type to unsigned to have an unsigned shift.
|
||||
let unsigned_type = result_type.to_unsigned(&self.cx);
|
||||
let unsigned_type = result_type.to_unsigned(self.cx);
|
||||
let shifted = self.gcc_lshr(
|
||||
self.gcc_int_cast(lhs, unsigned_type),
|
||||
self.gcc_int(unsigned_type, width as i64 - 1),
|
||||
|
|
|
|||
|
|
@ -73,11 +73,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let expected_bytes = len / 8 + ((len % 8 > 0) as u64);
|
||||
|
||||
let mask_ty = arg_tys[0];
|
||||
let mut mask = match mask_ty.kind() {
|
||||
let mut mask = match *mask_ty.kind() {
|
||||
ty::Int(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
|
||||
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
|
||||
ty::Array(elem, len)
|
||||
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||
if matches!(*elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||
&& len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
|
||||
== Some(expected_bytes) =>
|
||||
{
|
||||
|
|
@ -310,10 +310,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
})
|
||||
.collect();
|
||||
return Ok(bx.context.new_rvalue_from_vector(None, v_type, &elems));
|
||||
} else {
|
||||
// avoid the unnecessary truncation as an optimization.
|
||||
return Ok(bx.context.new_bitcast(None, result, v_type));
|
||||
}
|
||||
// avoid the unnecessary truncation as an optimization.
|
||||
return Ok(bx.context.new_bitcast(None, result, v_type));
|
||||
}
|
||||
// since gcc doesn't have vector shuffle methods available in non-patched builds, fallback to
|
||||
// component-wise bitreverses if they're not available.
|
||||
|
|
@ -358,8 +357,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
if name == sym::simd_shuffle {
|
||||
// Make sure this is actually an array, since typeck only checks the length-suffixed
|
||||
// version of this intrinsic.
|
||||
let n: u64 = match args[2].layout.ty.kind() {
|
||||
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
|
||||
let n: u64 = match *args[2].layout.ty.kind() {
|
||||
ty::Array(ty, len) if matches!(*ty.kind(), ty::Uint(ty::UintTy::U32)) => {
|
||||
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|
||||
|| span_bug!(span, "could not evaluate shuffle index array length"),
|
||||
)
|
||||
|
|
@ -432,7 +431,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
m_len == v_len,
|
||||
InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
|
||||
);
|
||||
match m_elem_ty.kind() {
|
||||
match *m_elem_ty.kind() {
|
||||
ty::Int(_) => {}
|
||||
_ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
|
||||
}
|
||||
|
|
@ -600,13 +599,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
Unsupported,
|
||||
}
|
||||
|
||||
let in_style = match in_elem.kind() {
|
||||
let in_style = match *in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Style::Int,
|
||||
ty::Float(_) => Style::Float,
|
||||
_ => Style::Unsupported,
|
||||
};
|
||||
|
||||
let out_style = match out_elem.kind() {
|
||||
let out_style = match *out_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Style::Int,
|
||||
ty::Float(_) => Style::Float,
|
||||
_ => Style::Unsupported,
|
||||
|
|
@ -633,7 +632,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
macro_rules! arith_binary {
|
||||
($($name: ident: $($($p: ident),* => $call: ident),*;)*) => {
|
||||
$(if name == sym::$name {
|
||||
match in_elem.kind() {
|
||||
match *in_elem.kind() {
|
||||
$($(ty::$p(_))|* => {
|
||||
return Ok(bx.$call(args[0].immediate(), args[1].immediate()))
|
||||
})*
|
||||
|
|
@ -671,7 +670,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let sign_shift = bx.context.new_rvalue_from_int(elem_type, elem_size as i32 - 1);
|
||||
let one = bx.context.new_rvalue_one(elem_type);
|
||||
|
||||
let mut shift = 0;
|
||||
for i in 0..in_len {
|
||||
let elem =
|
||||
bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32));
|
||||
|
|
@ -679,17 +677,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let masked = shifted & one;
|
||||
result = result
|
||||
| (bx.context.new_cast(None, masked, result_type)
|
||||
<< bx.context.new_rvalue_from_int(result_type, shift));
|
||||
shift += 1;
|
||||
<< bx.context.new_rvalue_from_int(result_type, i as i32));
|
||||
}
|
||||
|
||||
match ret_ty.kind() {
|
||||
match *ret_ty.kind() {
|
||||
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {
|
||||
// Zero-extend iN to the bitmask type:
|
||||
return Ok(result);
|
||||
}
|
||||
ty::Array(elem, len)
|
||||
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||
if matches!(*elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||
&& len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
|
||||
== Some(expected_bytes) =>
|
||||
{
|
||||
|
|
@ -728,7 +725,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
return Err(());
|
||||
}};
|
||||
}
|
||||
let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
|
||||
let (elem_ty_str, elem_ty) = if let ty::Float(ref f) = *in_elem.kind() {
|
||||
let elem_ty = bx.cx.type_float_from_ty(*f);
|
||||
match f.bit_width() {
|
||||
32 => ("f", elem_ty),
|
||||
|
|
@ -979,7 +976,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
|
||||
// The element type of the third argument must be a signed integer type of any width:
|
||||
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
match element_ty2.kind() {
|
||||
match *element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
require!(
|
||||
|
|
@ -1095,7 +1092,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
assert_eq!(underlying_ty, non_ptr(element_ty0));
|
||||
|
||||
// The element type of the third argument must be a signed integer type of any width:
|
||||
match element_ty2.kind() {
|
||||
match *element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
require!(
|
||||
|
|
@ -1153,7 +1150,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
macro_rules! arith_unary {
|
||||
($($name: ident: $($($p: ident),* => $call: ident),*;)*) => {
|
||||
$(if name == sym::$name {
|
||||
match in_elem.kind() {
|
||||
match *in_elem.kind() {
|
||||
$($(ty::$p(_))|* => {
|
||||
return Ok(bx.$call(args[0].immediate()))
|
||||
})*
|
||||
|
|
@ -1277,7 +1274,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
ret_ty == in_elem,
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
return match in_elem.kind() {
|
||||
return match *in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
let r = bx.vector_reduce_op(args[0].immediate(), $vec_op);
|
||||
if $ordered {
|
||||
|
|
@ -1346,7 +1343,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
ret_ty == in_elem,
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
return match in_elem.kind() {
|
||||
return match *in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
|
||||
ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
|
|
@ -1375,7 +1372,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
);
|
||||
args[0].immediate()
|
||||
} else {
|
||||
match in_elem.kind() {
|
||||
match *in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {}
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
|
|
@ -1389,7 +1386,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
|
||||
args[0].immediate()
|
||||
};
|
||||
return match in_elem.kind() {
|
||||
return match *in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
let r = bx.vector_reduce_op(input, $op);
|
||||
Ok(if !$boolean {
|
||||
|
|
|
|||
22
src/lib.rs
22
src/lib.rs
|
|
@ -22,6 +22,7 @@
|
|||
#![warn(rust_2018_idioms)]
|
||||
#![warn(unused_lifetimes)]
|
||||
#![deny(clippy::pattern_type_mismatch)]
|
||||
#![allow(clippy::needless_lifetimes)]
|
||||
|
||||
extern crate rustc_apfloat;
|
||||
extern crate rustc_ast;
|
||||
|
|
@ -84,7 +85,6 @@ use std::sync::Mutex;
|
|||
use back::lto::ThinBuffer;
|
||||
use back::lto::ThinData;
|
||||
use errors::LTONotSupported;
|
||||
#[cfg(not(feature = "master"))]
|
||||
use gccjit::CType;
|
||||
use gccjit::{Context, OptimizationLevel};
|
||||
#[cfg(feature = "master")]
|
||||
|
|
@ -140,6 +140,10 @@ impl TargetInfo {
|
|||
fn supports_128bit_int(&self) -> bool {
|
||||
self.supports_128bit_integers.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
fn supports_target_dependent_type(&self, _typ: CType) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -161,6 +165,10 @@ impl LockedTargetInfo {
|
|||
fn supports_128bit_int(&self) -> bool {
|
||||
self.info.lock().expect("lock").supports_128bit_int()
|
||||
}
|
||||
|
||||
fn supports_target_dependent_type(&self, typ: CType) -> bool {
|
||||
self.info.lock().expect("lock").supports_target_dependent_type(typ)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -446,7 +454,8 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
|
||||
#[cfg(feature = "master")]
|
||||
let info = {
|
||||
// Check whether the target supports 128-bit integers.
|
||||
// Check whether the target supports 128-bit integers, and sized floating point types (like
|
||||
// Float16).
|
||||
let context = Context::default();
|
||||
Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
|
||||
};
|
||||
|
|
@ -476,6 +485,7 @@ pub fn target_features(
|
|||
allow_unstable: bool,
|
||||
target_info: &LockedTargetInfo,
|
||||
) -> Vec<Symbol> {
|
||||
// TODO(antoyo): use global_gcc_features.
|
||||
sess.target
|
||||
.supported_target_features()
|
||||
.iter()
|
||||
|
|
@ -486,8 +496,12 @@ pub fn target_features(
|
|||
None
|
||||
}
|
||||
})
|
||||
.filter(|_feature| {
|
||||
target_info.cpu_supports(_feature)
|
||||
.filter(|feature| {
|
||||
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
|
||||
if *feature == "neon" {
|
||||
return false;
|
||||
}
|
||||
target_info.cpu_supports(feature)
|
||||
/*
|
||||
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
|
||||
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
|
||||
|
|
|
|||
82
src/type_.rs
82
src/type_.rs
|
|
@ -1,3 +1,8 @@
|
|||
#[cfg(feature = "master")]
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::CType;
|
||||
use gccjit::{RValue, Struct, Type};
|
||||
use rustc_codegen_ssa::common::TypeKind;
|
||||
use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
|
||||
|
|
@ -142,25 +147,76 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
fn type_f16(&self) -> Type<'gcc> {
|
||||
unimplemented!("f16_f128")
|
||||
#[cfg(feature = "master")]
|
||||
if self.supports_f16_type {
|
||||
return self.context.new_c_type(CType::Float16);
|
||||
}
|
||||
bug!("unsupported float width 16")
|
||||
}
|
||||
|
||||
fn type_f32(&self) -> Type<'gcc> {
|
||||
#[cfg(feature = "master")]
|
||||
if self.supports_f32_type {
|
||||
return self.context.new_c_type(CType::Float32);
|
||||
}
|
||||
self.float_type
|
||||
}
|
||||
|
||||
fn type_f64(&self) -> Type<'gcc> {
|
||||
#[cfg(feature = "master")]
|
||||
if self.supports_f64_type {
|
||||
return self.context.new_c_type(CType::Float64);
|
||||
}
|
||||
self.double_type
|
||||
}
|
||||
|
||||
fn type_f128(&self) -> Type<'gcc> {
|
||||
unimplemented!("f16_f128")
|
||||
#[cfg(feature = "master")]
|
||||
if self.supports_f128_type {
|
||||
return self.context.new_c_type(CType::Float128);
|
||||
}
|
||||
bug!("unsupported float width 128")
|
||||
}
|
||||
|
||||
fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
|
||||
self.context.new_function_pointer_type(None, return_type, params, false)
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
|
||||
if self.is_int_type_or_bool(typ) {
|
||||
TypeKind::Integer
|
||||
} else if typ.get_pointee().is_some() {
|
||||
TypeKind::Pointer
|
||||
} else if typ.is_vector() {
|
||||
TypeKind::Vector
|
||||
} else if typ.dyncast_array().is_some() {
|
||||
TypeKind::Array
|
||||
} else if typ.is_struct().is_some() {
|
||||
TypeKind::Struct
|
||||
} else if typ.dyncast_function_ptr_type().is_some() {
|
||||
TypeKind::Function
|
||||
} else if typ.is_compatible_with(self.float_type) {
|
||||
TypeKind::Float
|
||||
} else if typ.is_compatible_with(self.double_type) {
|
||||
TypeKind::Double
|
||||
} else if typ.is_floating_point() {
|
||||
match typ.get_size() {
|
||||
2 => TypeKind::Half,
|
||||
4 => TypeKind::Float,
|
||||
8 => TypeKind::Double,
|
||||
16 => TypeKind::FP128,
|
||||
size => unreachable!("Floating-point type of size {}", size),
|
||||
}
|
||||
} else if typ == self.type_void() {
|
||||
TypeKind::Void
|
||||
} else {
|
||||
// TODO(antoyo): support other types.
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "master"))]
|
||||
fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
|
||||
if self.is_int_type_or_bool(typ) {
|
||||
TypeKind::Integer
|
||||
|
|
@ -170,9 +226,19 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
TypeKind::Double
|
||||
} else if typ.is_vector() {
|
||||
TypeKind::Vector
|
||||
} else if typ.get_pointee().is_some() {
|
||||
TypeKind::Pointer
|
||||
} else if typ.dyncast_array().is_some() {
|
||||
TypeKind::Array
|
||||
} else if typ.is_struct().is_some() {
|
||||
TypeKind::Struct
|
||||
} else if typ.dyncast_function_ptr_type().is_some() {
|
||||
TypeKind::Function
|
||||
} else if typ == self.type_void() {
|
||||
TypeKind::Void
|
||||
} else {
|
||||
// TODO(antoyo): support other types.
|
||||
TypeKind::Void
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,6 +266,16 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
unimplemented!();
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
fn float_width(&self, typ: Type<'gcc>) -> usize {
|
||||
if typ.is_floating_point() {
|
||||
(typ.get_size() * u8::BITS).try_into().unwrap()
|
||||
} else {
|
||||
panic!("Cannot get width of float type {:?}", typ);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "master"))]
|
||||
fn float_width(&self, typ: Type<'gcc>) -> usize {
|
||||
let f32 = self.context.new_type::<f32>();
|
||||
let f64 = self.context.new_type::<f64>();
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
|
|||
Abi::Uninhabited | Abi::Aggregate { .. } => {}
|
||||
}
|
||||
|
||||
let name = match layout.ty.kind() {
|
||||
let name = match *layout.ty.kind() {
|
||||
// FIXME(eddyb) producing readable type names for trait objects can result
|
||||
// in problematically distinct types due to HRTB and subtyping (see #47638).
|
||||
// ty::Dynamic(..) |
|
||||
|
|
@ -214,7 +214,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||
// to fn_ptr_backend_type handle the on-stack attribute.
|
||||
// TODO(antoyo): find a less hackish way to hande the on-stack attribute.
|
||||
ty::FnPtr(sig) => {
|
||||
cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
|
||||
cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
|
||||
}
|
||||
_ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue