Skip to content

Wrong return type of extern functions #10592

Closed
@honzasp

Description

@honzasp

Hi,

I was trying to use the LLVM C bindings from Rust, but I ran into a mysterious error when I tried to use LLVMGetTypeKind. The Rust program is like this:

#[allow(cstack)];
use std::libc::{c_uint};

pub enum Context_opaque {}
pub type ContextPtr = *Context_opaque;
pub enum Type_opaque {}
pub type TypePtr = *Type_opaque;

#[repr(C)]
pub enum LLVMTypeKind {
  LLVMVoidTypeKind,
  LLVMHalfTypeKind,
  LLVMFloatTypeKind,
  LLVMDoubleTypeKind,
  LLVMX86_FP80TypeKind,
  LLVMFP128TypeKind,
  LLVMPPC_FP128TypeKind,
  LLVMLabelTypeKind,
  LLVMIntegerTypeKind,
  LLVMFunctionTypeKind,
  LLVMStructTypeKind,
  LLVMArrayTypeKind,
  LLVMPointerTypeKind,
  LLVMVectorTypeKind,
  LLVMMetadataTypeKind,
  LLVMX86_MMXTypeKind
}

#[link_args = "-lLLVMCore -lLLVMSupport"]
extern {
  pub fn LLVMContextCreate() -> ContextPtr;
  pub fn LLVMContextDispose(c: ContextPtr);
  pub fn LLVMGetTypeKind(t: TypePtr) -> LLVMTypeKind;
  pub fn LLVMIntTypeInContext(c: ContextPtr, bits: c_uint) -> TypePtr;
}

fn main() {
  unsafe {
    let ctx_ptr = LLVMContextCreate();
    let int32_ptr = LLVMIntTypeInContext(ctx_ptr, 32);
    let kind = LLVMGetTypeKind(int32_ptr); // boom!
    println!("{}", kind as uint);
    LLVMContextDispose(ctx_ptr);
  }
}

When compiled and executed, LLVM crashes with

Unhandled TypeID.
UNREACHABLE executed at Core.cpp:164!
Aborted (core dumped)

After some investigation, I made rustc emit LLVM bitcode and found something strange:

declare void @LLVMGetTypeKind(%enum.LLVMTypeKind* sret, %enum.Type_opaque*) unnamed_addr

call void @LLVMGetTypeKind(%enum.LLVMTypeKind* sret %kind, %enum.Type_opaque* %11)

rustc declared the LLVMGetTypeKind function with wrong parameters, so the function, when called, got a pointer to unitialized value on stack instead of a ContextRef.

I tried to declare LLVMGetTypeKind as a function returning c_uint and everything worked well (it is probably the reason why rustc's LLVM bindings declare LLVMTypeKind as a series of static variables).

Is this a bug or a feature? If it is a feature, it is worth documenting! :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-FFIArea: Foreign function interface (FFI)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions