Skip to content
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

Consistent AccessViolationException when calling BuildCall2 #227

Closed
DuncanMcPherson opened this issue Nov 19, 2024 · 2 comments
Closed

Consistent AccessViolationException when calling BuildCall2 #227

DuncanMcPherson opened this issue Nov 19, 2024 · 2 comments

Comments

@DuncanMcPherson
Copy link

I have a project that is using LLVM and I am trying to write my own implementation of the C Standard library's strlen. I got what I though would be a valid declaration:

private void DeclareStrLen()
{
    var strlenType = LLVMTypeRef.CreateFunction(LLVMTypeRef.Int32,
        new[] { LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0) }, false);
    var strlenFunction = _module.GetNamedFunction("strlen");
    if (strlenFunction.Handle != IntPtr.Zero)
    {
        return;
    }

    strlenFunction = _module.AddFunction("strlen", strlenType);

    var entry = strlenFunction.AppendBasicBlock("entry");
    _builder.PositionAtEnd(entry);

    var str = strlenFunction.GetParam(0);

    var length = _builder.BuildAlloca(LLVMTypeRef.Int32, "length");
    _builder.BuildStore(LLVMValueRef.CreateConstInt(LLVMTypeRef.Int32, 0, false), length);

    var loopCond = strlenFunction.AppendBasicBlock("loopCond");
    var loopBody = strlenFunction.AppendBasicBlock("loopBody");
    var loopEnd = strlenFunction.AppendBasicBlock("loopEnd");

    _builder.BuildBr(loopCond);

    _builder.PositionAtEnd(loopCond);
    var currentIndex = _builder.BuildLoad2(LLVMTypeRef.Int32, length, "currentIndex");
    var currentCharPtr = _builder.BuildInBoundsGEP2(LLVMTypeRef.Int8, str, new LLVMValueRef[] { currentIndex });
    var currentChar = _builder.BuildLoad2(LLVMTypeRef.Int8, currentCharPtr, "currentChar");
    var isNullChar = _builder.BuildICmp(LLVMIntPredicate.LLVMIntEQ, currentChar,
        LLVMValueRef.CreateConstInt(LLVMTypeRef.Int8, 0, false), "isNullChar");

    _builder.BuildCondBr(isNullChar, loopEnd, loopBody);

    _builder.PositionAtEnd(loopBody);
    var newIndex = _builder.BuildAdd(currentIndex, LLVMValueRef.CreateConstInt(LLVMTypeRef.Int32, 1, false),
        "newIndex");
    _builder.BuildStore(newIndex, length);
    _builder.BuildBr(loopCond);

    _builder.PositionAtEnd(loopEnd);
    var finalLength = _builder.BuildLoad2(LLVMTypeRef.Int32, length, "finalLength");
    _builder.BuildRet(finalLength);
}

However, when I tried to do something like var length = _builder.BuildCall2(_module.GetNamedFunction("strlen").TypeOf, _module.GetNamedFunction("strlen"), [/*valueRef here*/]);
I always got an AccessViolationException.
At first, I thought it was an issue with my code, but after 2-3 hours of debugging and conferring with peers, no answers could be found. Please help

@davidelettieri
Copy link

Hi, I think the problem might be similar to this #221 (comment)

If you look at the implementation of the TypeOf property on LLVMValueRef you can see

public LLVMTypeRef TypeOf => (Handle != IntPtr.Zero) ? LLVM.TypeOf(this) : default;

However the LLVM.TypeOf method is not working anymore on types of kind LLVMPointerTypeKind. I think you have two options:

  1. You know the type of the function because you are defining it so you can rebuild the type as you did when defining strlenType.
  2. Retrieve the type using LLVM.GlobalGetValueType on the function.

In case of 2 you will have

var func = _module.GetNamedFunction("strlen");
var funcType = LLVM.GlobalGetValueType(func);
var v = _builder.BuildCall2(funcType2, func, [/*valueRef here*/]);

Let me know if this helps.

@DuncanMcPherson
Copy link
Author

Let me know if this helps.

Thank you so much! I had been working at that issue for 3 days! and the second approach worked perfectly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants