Skip to content

cg_llvm: Use LLVM-C bindings for LLVMSetTailCallKind, LLVMGetTypeKind #145420

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
instance: Option<Instance<'tcx>>,
) {
let call = self.call(llty, fn_attrs, Some(fn_abi), llfn, args, funclet, instance);
llvm::LLVMRustSetTailCallKind(call, llvm::TailCallKind::MustTail);
llvm::LLVMSetTailCallKind(call, llvm::TailCallKind::MustTail);

match &fn_abi.ret.mode {
PassMode::Ignore | PassMode::Indirect { .. } => self.ret_void(),
Expand Down
19 changes: 12 additions & 7 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub(crate) enum ModuleFlagMergeBehavior {

// Consts for the LLVM CallConv type, pre-cast to usize.

/// Must match the layout of `LLVMTailCallKind`.
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C)]
#[allow(dead_code)]
Expand Down Expand Up @@ -332,10 +333,15 @@ impl RealPredicate {
}
}

/// LLVMTypeKind
#[derive(Copy, Clone, PartialEq, Debug)]
/// Must match the layout of `LLVMTypeKind`.
///
/// Use [`RawEnum<TypeKind>`] for values of `LLVMTypeKind` returned from LLVM,
/// to avoid risk of UB if LLVM adds new enum values.
///
/// All of LLVM's variants should be declared here, even if no Rust-side code refers
/// to them, because unknown variants will cause [`RawEnum::to_rust`] to panic.
#[derive(Copy, Clone, PartialEq, Debug, TryFromU32)]
#[repr(C)]
#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")]
pub(crate) enum TypeKind {
Void = 0,
Half = 1,
Expand Down Expand Up @@ -1046,6 +1052,8 @@ unsafe extern "C" {
CanThrow: llvm::Bool,
) -> &'ll Value;

pub(crate) safe fn LLVMGetTypeKind(Ty: &Type) -> RawEnum<TypeKind>;

// Operations on integer types
pub(crate) fn LLVMInt1TypeInContext(C: &Context) -> &Type;
pub(crate) fn LLVMInt8TypeInContext(C: &Context) -> &Type;
Expand Down Expand Up @@ -1197,7 +1205,7 @@ unsafe extern "C" {
pub(crate) safe fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
pub(crate) safe fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
pub(crate) safe fn LLVMRustSetTailCallKind(CallInst: &Value, Kind: TailCallKind);
pub(crate) safe fn LLVMSetTailCallKind(CallInst: &Value, kind: TailCallKind);

// Operations on attributes
pub(crate) fn LLVMCreateStringAttribute(
Expand Down Expand Up @@ -1841,9 +1849,6 @@ unsafe extern "C" {
// Create and destroy contexts.
pub(crate) fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;

/// See llvm::LLVMTypeKind::getTypeID.
pub(crate) fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;

// Operations on all values
pub(crate) fn LLVMRustGlobalAddMetadata<'a>(
Val: &'a Value,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> {
}

fn type_kind(&self, ty: &'ll Type) -> TypeKind {
unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() }
llvm::LLVMGetTypeKind(ty).to_rust().to_generic()
}

fn type_ptr(&self) -> &'ll Type {
Expand Down
80 changes: 0 additions & 80 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1460,60 +1460,6 @@ LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
return toRust((DiagnosticKind)unwrap(DI)->getKind());
}

// This is kept distinct from LLVMGetTypeKind, because when
// a new type kind is added, the Rust-side enum must be
// updated or UB will result.
extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
switch (unwrap(Ty)->getTypeID()) {
case Type::VoidTyID:
return LLVMVoidTypeKind;
case Type::HalfTyID:
return LLVMHalfTypeKind;
case Type::FloatTyID:
return LLVMFloatTypeKind;
case Type::DoubleTyID:
return LLVMDoubleTypeKind;
case Type::X86_FP80TyID:
return LLVMX86_FP80TypeKind;
case Type::FP128TyID:
return LLVMFP128TypeKind;
case Type::PPC_FP128TyID:
return LLVMPPC_FP128TypeKind;
case Type::LabelTyID:
return LLVMLabelTypeKind;
case Type::MetadataTyID:
return LLVMMetadataTypeKind;
case Type::IntegerTyID:
return LLVMIntegerTypeKind;
case Type::FunctionTyID:
return LLVMFunctionTypeKind;
case Type::StructTyID:
return LLVMStructTypeKind;
case Type::ArrayTyID:
return LLVMArrayTypeKind;
case Type::PointerTyID:
return LLVMPointerTypeKind;
case Type::FixedVectorTyID:
return LLVMVectorTypeKind;
case Type::TokenTyID:
return LLVMTokenTypeKind;
case Type::ScalableVectorTyID:
return LLVMScalableVectorTypeKind;
case Type::BFloatTyID:
return LLVMBFloatTypeKind;
case Type::X86_AMXTyID:
return LLVMX86_AMXTypeKind;
default: {
std::string error;
auto stream = llvm::raw_string_ostream(error);
stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID()
<< " for the type: " << *unwrap(Ty);
stream.flush();
report_fatal_error(error.c_str());
}
}
}

DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)

extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(LLVMDiagnosticInfoRef DI,
Expand Down Expand Up @@ -1993,29 +1939,3 @@ extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) {
MD.NoHWAddress = true;
GV.setSanitizerMetadata(MD);
}

enum class LLVMRustTailCallKind {
None = 0,
Tail = 1,
MustTail = 2,
NoTail = 3
};

extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call,
LLVMRustTailCallKind Kind) {
CallInst *CI = unwrap<CallInst>(Call);
switch (Kind) {
case LLVMRustTailCallKind::None:
CI->setTailCallKind(CallInst::TCK_None);
break;
case LLVMRustTailCallKind::Tail:
CI->setTailCallKind(CallInst::TCK_Tail);
break;
case LLVMRustTailCallKind::MustTail:
CI->setTailCallKind(CallInst::TCK_MustTail);
break;
case LLVMRustTailCallKind::NoTail:
CI->setTailCallKind(CallInst::TCK_NoTail);
break;
}
}
Loading