Skip to content

Commit 882f72d

Browse files
committed
Change codegen of LLVM intrinsics to be name-based
1 parent 2c12b4a commit 882f72d

File tree

12 files changed

+363
-31
lines changed

12 files changed

+363
-31
lines changed

compiler/rustc_codegen_gcc/src/type_of.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt::Write;
22

3-
use gccjit::{Struct, Type};
3+
use gccjit::{RValue, Struct, Type};
44
use rustc_abi as abi;
55
use rustc_abi::Primitive::*;
66
use rustc_abi::{
@@ -373,7 +373,11 @@ impl<'gcc, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
373373
unimplemented!();
374374
}
375375

376-
fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
376+
fn fn_decl_backend_type(
377+
&self,
378+
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
379+
_fn_ptr: RValue<'gcc>,
380+
) -> Type<'gcc> {
377381
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
378382
let FnAbiGcc { return_type, arguments_type, is_c_variadic, .. } = fn_abi.gcc_type(self);
379383
self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::borrow::Borrow;
22
use std::cmp;
3+
use std::iter::zip;
34

45
use libc::c_uint;
56
use rustc_abi::{BackendRepr, HasDataLayout, Primitive, Reg, RegKind, Size};
@@ -308,7 +309,9 @@ impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
308309
}
309310

310311
pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
311-
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
312+
fn llvm_return_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
313+
fn llvm_argument_types(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<&'ll Type>;
314+
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>, name: &[u8]) -> &'ll Type;
312315
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
313316
fn llvm_cconv(&self, cx: &CodegenCx<'ll, 'tcx>) -> llvm::CallConv;
314317

@@ -325,26 +328,29 @@ pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
325328
}
326329

327330
impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
328-
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
331+
fn llvm_return_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
332+
match &self.ret.mode {
333+
PassMode::Ignore => cx.type_void(),
334+
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
335+
PassMode::Cast { cast, pad_i32: _ } => cast.llvm_type(cx),
336+
PassMode::Indirect { .. } => cx.type_void(),
337+
}
338+
}
339+
340+
fn llvm_argument_types(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<&'ll Type> {
341+
let indirect_return = matches!(self.ret.mode, PassMode::Indirect { .. });
342+
329343
// Ignore "extra" args from the call site for C variadic functions.
330344
// Only the "fixed" args are part of the LLVM function signature.
331345
let args =
332346
if self.c_variadic { &self.args[..self.fixed_count as usize] } else { &self.args };
333347

334-
// This capacity calculation is approximate.
335-
let mut llargument_tys = Vec::with_capacity(
336-
self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 },
337-
);
348+
let mut llargument_tys =
349+
Vec::with_capacity(args.len() + if indirect_return { 1 } else { 0 });
338350

339-
let llreturn_ty = match &self.ret.mode {
340-
PassMode::Ignore => cx.type_void(),
341-
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
342-
PassMode::Cast { cast, pad_i32: _ } => cast.llvm_type(cx),
343-
PassMode::Indirect { .. } => {
344-
llargument_tys.push(cx.type_ptr());
345-
cx.type_void()
346-
}
347-
};
351+
if indirect_return {
352+
llargument_tys.push(cx.type_ptr());
353+
}
348354

349355
for arg in args {
350356
// Note that the exact number of arguments pushed here is carefully synchronized with
@@ -391,10 +397,45 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
391397
llargument_tys.push(llarg_ty);
392398
}
393399

394-
if self.c_variadic {
395-
cx.type_variadic_func(&llargument_tys, llreturn_ty)
400+
llargument_tys
401+
}
402+
403+
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>, name: &[u8]) -> &'ll Type {
404+
let actual_return_ty = self.llvm_return_type(cx);
405+
let actual_argument_tys = self.llvm_argument_types(cx);
406+
407+
if name.starts_with(b"llvm.")
408+
&& let Some((intrinsic, type_params)) = cx.parse_intrinsic_name(name)
409+
{
410+
let fn_ty = cx.intrinsic_type(intrinsic, &type_params);
411+
412+
let expected_return_ty = cx.get_return_type(fn_ty);
413+
let expected_argument_tys = cx.func_params_types(fn_ty);
414+
415+
let equate_ty = |rust_ty, llvm_ty| rust_ty == llvm_ty;
416+
417+
if actual_argument_tys.len() != expected_argument_tys.len() {
418+
todo!("A very friendly error msg")
419+
}
420+
421+
if !equate_ty(actual_return_ty, expected_return_ty) {
422+
todo!("A very friendly error msg")
423+
}
424+
for (actual_argument_ty, expected_argument_ty) in
425+
zip(actual_argument_tys, expected_argument_tys)
426+
{
427+
if !equate_ty(actual_argument_ty, expected_argument_ty) {
428+
todo!("A very friendly error msg")
429+
}
430+
}
431+
432+
fn_ty
396433
} else {
397-
cx.type_func(&llargument_tys, llreturn_ty)
434+
if self.c_variadic {
435+
cx.type_variadic_func(&actual_argument_tys, actual_return_ty)
436+
} else {
437+
cx.type_func(&actual_argument_tys, actual_return_ty)
438+
}
398439
}
399440
}
400441

compiler/rustc_codegen_llvm/src/declare.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
158158
fn_abi.llvm_cconv(self),
159159
llvm::UnnamedAddr::Global,
160160
llvm::Visibility::Default,
161-
fn_abi.llvm_type(self),
161+
fn_abi.llvm_type(self, name.as_ref()),
162162
);
163163
fn_abi.apply_attrs_llfn(self, llfn, instance);
164164

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ fn gen_fn<'a, 'll, 'tcx>(
11021102
codegen: &mut dyn FnMut(Builder<'a, 'll, 'tcx>),
11031103
) -> (&'ll Type, &'ll Value) {
11041104
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
1105-
let llty = fn_abi.llvm_type(cx);
1105+
let llty = fn_abi.llvm_type(cx, name.as_ref());
11061106
let llfn = cx.declare_fn(name, fn_abi, None);
11071107
cx.set_frame_pointer_type(llfn);
11081108
cx.apply_target_cpu_attr(llfn);

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,11 @@ unsafe extern "C" {
10501050
pub(crate) fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
10511051
pub(crate) fn LLVMFP128TypeInContext(C: &Context) -> &Type;
10521052

1053+
// non-IEEE fp types
1054+
pub(crate) fn LLVMBFloatTypeInContext(C: &Context) -> &Type;
1055+
pub(crate) fn LLVMX86FP80TypeInContext(C: &Context) -> &Type;
1056+
pub(crate) fn LLVMPPCFP128TypeInContext(C: &Context) -> &Type;
1057+
10531058
// Operations on function types
10541059
pub(crate) fn LLVMFunctionType<'a>(
10551060
ReturnType: &'a Type,
@@ -1071,6 +1076,10 @@ unsafe extern "C" {
10711076
// Operations on array, pointer, and vector types (sequence types)
10721077
pub(crate) fn LLVMPointerTypeInContext(C: &Context, AddressSpace: c_uint) -> &Type;
10731078
pub(crate) fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
1079+
pub(crate) fn LLVMScalableVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
1080+
1081+
// Special X86 Type for AMX
1082+
pub(crate) fn LLVMX86AMXTypeInContext(C: &Context) -> &Type;
10741083

10751084
pub(crate) fn LLVMGetElementType(Ty: &Type) -> &Type;
10761085
pub(crate) fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint;
@@ -1195,6 +1204,26 @@ unsafe extern "C" {
11951204
// Operations on functions
11961205
pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
11971206

1207+
// Operations about llvm intrinsics
1208+
pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint;
1209+
pub(crate) fn LLVMGetIntrinsicDeclaration<'a>(
1210+
M: &'a Module,
1211+
ID: c_uint,
1212+
ParamTypes: *const &'a Type,
1213+
ParamCount: size_t,
1214+
) -> &'a Value;
1215+
pub(crate) fn LLVMIntrinsicGetType<'a>(
1216+
C: &'a Context,
1217+
ID: c_uint,
1218+
ParamTypes: *const &'a Type,
1219+
ParamCount: size_t,
1220+
) -> &'a Type;
1221+
pub(crate) fn LLVMRustIntrinsicGetBaseName(
1222+
ID: c_uint,
1223+
NameLength: *mut size_t,
1224+
) -> *const c_char;
1225+
pub(crate) fn LLVMIntrinsicIsOverloaded(ID: c_uint) -> Bool;
1226+
11981227
// Operations on parameters
11991228
pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>;
12001229
pub(crate) safe fn LLVMCountParams(Fn: &Value) -> c_uint;

compiler/rustc_codegen_llvm/src/llvm/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![allow(non_snake_case)]
22

3+
use core::slice;
34
use std::ffi::{CStr, CString};
45
use std::ptr;
56
use std::str::FromStr;
@@ -327,6 +328,32 @@ pub(crate) fn get_value_name(value: &Value) -> &[u8] {
327328
}
328329
}
329330

331+
#[derive(Debug, Copy, Clone)]
332+
pub(crate) struct Intrinsic {
333+
id: c_uint,
334+
}
335+
336+
impl Intrinsic {
337+
pub(crate) fn lookup(name: &[u8]) -> Option<Self> {
338+
let id = unsafe { LLVMLookupIntrinsicID(name.as_c_char_ptr(), name.len()) };
339+
if id == 0 { None } else { Some(Self { id }) }
340+
}
341+
342+
pub(crate) fn id(self) -> c_uint {
343+
self.id
344+
}
345+
346+
pub(crate) fn is_overloaded(self) -> bool {
347+
unsafe { LLVMIntrinsicIsOverloaded(self.id) == True }
348+
}
349+
350+
pub(crate) fn base_name<'ll>(self) -> &'ll [u8] {
351+
let mut len = 0;
352+
let ptr = unsafe { LLVMRustIntrinsicGetBaseName(self.id, &mut len) };
353+
unsafe { slice::from_raw_parts(ptr.cast(), len) }
354+
}
355+
}
356+
330357
/// Safe wrapper for `LLVMSetValueName2` from a byte slice
331358
pub(crate) fn set_value_name(value: &Value, name: &[u8]) {
332359
unsafe {

0 commit comments

Comments
 (0)