Skip to content

BuildCall2 fails with assertion error when passing variadic arguments to printf #229

Open
@dadavadd

Description

@dadavadd

Description

When trying to use BuildCall2 to call the printf function, I'm encountering an assertion error related to type mismatch in variadic arguments. The error occurs specifically when passing an integer value as a variadic argument to printf.

Error Message

Assertion failed: (i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && "Calling a function with a bad signature!", file C:\src\llvm_package_6923b0a7\llvm-project\llvm\lib\IR\Instructions.cpp, line 455

Code Example

Here's a simplified version of my code that reproduces the issue:

public LLVMValueRef VisitPrintStatement(CodeParser.PrintStatementContext context)
{
    string variableName = context.ID().GetText();
    if (!_variables.TryGetValue(variableName, out var variable))
    {
        throw new Exception($"Variable {variableName} is not defined.");
    }

    // Load integer value from allocated memory
    var varType = variable.TypeOf.ElementType;
    var value = Builder.BuildLoad2(varType, variable, $"{variableName}_value");
    
    // Create format string for printf
    string formatStr = "%d\n";
    var formatStrPtr = Builder.BuildGlobalStringPtr(formatStr, "formatStr");
    
    // Define printf function
    var printfType = LLVMTypeRef.CreateFunction(LLVMTypeRef.Int32, [LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0)], true);
    var func = GetOrInsertFunction("printf", printfType);
    
    // Call printf - this line causes the assertion error
    var call = Builder.BuildCall2(func.TypeOf, func, [formatStrPtr, value]);
    
    return call;
}

Debugging Information

I've examined the types right before the assertion fails:

  • printfType = {i32 (i8*, ...)}
  • func = {declare i32 @printf(i8*, ...)}
  • formatStrPtr = {i8* getelementptr inbounds ([4 x i8], [4 x i8]* @formatStr, i32 0, i32 0)}
  • args[0] = {i8* getelementptr inbounds ([4 x i8], [4 x i8]* @formatStr, i32 0, i32 0)}
  • args[1] = { %value1_value = load i32, i32* %value1, align 4}

Expected Behavior

I expect BuildCall2 to properly handle variadic functions and their arguments, especially for common use cases like printf with integer arguments.

Environment

  • LLVMSharp version: Latest in nuget.
  • .NET version: .NET 9
  • OS: Windows

Any guidance would be greatly appreciated!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions