Skip to content

Procedures lose polymorphis/fail assert of procedure type arguments after one call layer #5214

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

Open
Ferinzz opened this issue May 25, 2025 · 0 comments

Comments

@Ferinzz
Copy link

Ferinzz commented May 25, 2025

Context

Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    Odin:    dev-2025-04-nightly:d9f990d
    OS:      Windows 11 Professional (version: 23H2), build 22631.5335
    CPU:     13th Gen Intel(R) Core(TM) i5-13600K
    RAM:     32540 MiB
    Backend: LLVM 20.1.0

Expected Behavior

When using polymorphic procedures we should be able to pass procs as variables from one procedure to another.
When passing a proc as a variable between multiple procs we should not lose track of which one is being passed and create additional conditions based on this.

Current Behavior

Instead a llvm assert may fail or the compiler will choose one function to use for all calls from the second polymorphic procedure.

Failure Information (for bugs)

When compiling both as exe and shared-lib
D:\a\Odin\Odin\src\llvm_backend_general.cpp(2702): Assertion Failure: e->kind == Entity_Procedure

If it does not fail the assert you may have the second procedure always pointing to the same memory address. This is inconsistent between compilations.

testproc proc(^GDExample, i64) @ 0x7FF6CD7243C0
function passed to bindtodind: proc(^GDExample, i64) @ 0x7FF6CD7243C0
my argcount: 1
Bind function proc(^GDExample) @ 0x7FF6CD724650
testproc0 proc(^GDExample) @ 0x7FF6CD724650
function passed to bindtodind: proc(^GDExample) @ 0x7FF6CD724650
my argcount: 1
Bind function proc(^GDExample) @ 0x7FF6CD724650
testproc1 proc(^GDExample) -> f32 @ 0x7FF6CD724820
function passed to bindtodind: proc(^GDExample) -> f32 @ 0x7FF6CD724820
my argcount: 1
Bind function proc(^GDExample) @ 0x7FF6CD724650

Steps to Reproduce

Please provide detailed steps for reproducing the issue.

  1. create a proc
  2. create a function that accepts a polymorphic proc. proc($function: $T)
  3. call the polymorphic proc directly. Works as expected.
  4. create a second function which accepts a polymorphic proc. Call this function from the first polymorphic proc.
  5. compiler fails the assert llvm_backend_general.cpp(2702).
  6. If it does not fail the assert you may only have one memory address/type set for the second polymorphic proc. (I haven't been able to narrow this one down.)

Failure Logs

See above?

Reproduction Code

`package main

import sics "base:intrinsics"

main :: proc() {

//This causes the segfault
bindMethod1(ClassSetAmplitude)

//This is fine.
bindNoReturn2(ClassSetAmplitude)

}

//ENTRY POINT: This name needs to match the name in the gdexample.gdextension file.
//If the name does not match, Godot will not know where/how to bind to function.
//@export
//gdexample_library_init :: proc "contextless" () -> b8 {
// context = runtime.default_context()
//
// //This causes the segfault
// bindMethod1(ClassSetAmplitude)
//
// //This is fine.
// bindNoReturn2(ClassSetAmplitude)
// return true
//}

GDExample :: struct{
amplitude: f64,
}

ClassSetAmplitude :: proc "c" (self: ^GDExample, amplitude: f64) {
self.amplitude = amplitude
}

//where sics.type_is_proc(T)
bindMethod1 :: proc "c" (function: $T) where sics.type_is_proc(T) {
bindNoReturn2(function)
}

//Send callbacks to Godot. For testing I added the return, but this return should go to Godot for it to send back.
//-> (GDE.GDExtensionClassMethodPtrCall, GDE.GDExtensionClassMethodCall) where sics.type_is_proc(P)
bindNoReturn2 :: proc "c" ($T: $P) {
/*
context = runtime.default_context()
argcount:: sics.type_proc_parameter_count(P)
argT0 :: sics.type_proc_parameter_type(P, 0)

//fmt.println("func arg count: ", argcount)
//fmt.println("function ptr: ", T)

    argT1 :: sics.type_proc_parameter_type(P, 1)
    when argcount == 2 {
    
    godotPtrCallback :: proc "c" (method_userdata: rawptr, p_instance: GDE.GDExtensionClassInstancePtr, p_args: GDE.GDExtensionConstTypePtrargs, r_ret: GDE.GDExtensionTypePtr){
        context = runtime.default_context()
    }
    godotVariantCallback :: proc "c" (method_userdata: rawptr, p_instance: GDE.GDExtensionClassInstancePtr,
        p_args: GDE.GDExtensionConstVariantPtrargs, p_argument_count: GDE.GDExtensionInt, r_return: GDE.GDExtensionVariantPtr, r_error: ^GDE.GDExtensionCallError) {
    }
//return godotPtrCallback, godotVariantCallback
} else {#panic("RIP, no binding that fits with your arg count. Should be at least one pointer to the class struct and less than 12")}*/

}`

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

1 participant