HaxeFoundation / HaxeFoundation/haxe

`@:hlNative` on extern function silently omits native registrations in HL target

Open
#12,878 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
Haxe
Stars
6.9k
Forks
715
Avg merge
2d 2h
Merged PRs (30d)
11

Description

**Haxe version:** latest (reproduced on 4.x)
**Target:** HashLink (hl)

### Description

When using `@:hlNative` on an `extern` function inside a regular class, the compiler does not emit native function entries into the `.hl` bytecode. As a result, HashLink cannot resolve the functions at runtime and either crashes with `JIT ERROR -1` or `Failed to load function`.

The same binding works correctly when the function has a stub body (`{ return null; }`) without the `extern` keyword.

### Reproduction

**Working:**
```haxe
class SysNative {
@:hlNative("std", "sys_locale")
static public function sysLocale(): hl.Bytes { return null; }
}
```

**Not working (no compile-time error, runtime crash):**
```haxe
class SysNative {
@:hlNative("std", "sys_locale")
static extern public function sysLocale(): hl.Bytes;
}
```

### Investigation

Comparing the two compiled `.hl` files shows that in the `extern` function variant, the native function name (`sys_locale`) is completely absent from the bytecode string table. The native entry is never written, so `functions_indexes` for that findex remains `0xFFFFFFFF`, which triggers `ASSERT(fid)` in [`jit.c:1585`](https://github.com/HaxeFoundation/hashlink/blob/981e1a69a537943d7b2d1e8647cf14b0363a1f53/src/jit.c#L1585) (`op_call_fun`).

Attempting to compile with `--hl out.c` also throws `Invalid_argument("index out of bounds")` for the extern variant, further confirming the issue is in the compiler emit phase.

### Expected behavior

`@:hlNative` on an `extern` function should produce the same bytecode output as on a regular function with a stub body, consistent with how the feature works on other targets.

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue with the two `@:hlNative` examples and compare their `.hl` output, including the missing native name. Start with the compiler emit phase and `--hl out.c`; use HashLink `jit.c:1585` as the runtime failure reference. Done means the extern form emits the same native registration as the stub-body form.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.