Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/typescript-parity-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ Below is the detailed audit of all TypeScript/ECMAScript Abstract Syntax Tree (A
| **Dynamic `import('./mod')`** | ❌ Unsupported | Currently supports closed static module graphs only (AOT static linking). |
| **`eval()` & `new Function()`** | ❌ Unavailable in Native | Native machine binaries cannot interpret arbitrary JS strings at runtime (requires `--dynamic`). |
| **`Reflect` Namespace** | ✅ Full | All 19 standard ECMAScript & metadata APIs (`get`, `set`, `has`, `deleteProperty`, `ownKeys`, `defineProperty`, `getOwnPropertyDescriptor`, `getPrototypeOf`, `setPrototypeOf`, `isExtensible`, `preventExtensions`, `apply`, `construct`, `getMetadata`, `getOwnMetadata`, `hasMetadata`, `hasOwnMetadata`, `defineMetadata`, `metadata`) supported in Static Tier. |
| **`Proxy` Objects** | ⏳ Roadmap (Dynamic) | Dynamic field interception traps (get/set traps on arbitrary dynamic objects) slated for `--dynamic` tier. |
| **`Proxy` Objects** | ✅ Supported (--dynamic) | Basic Proxy interception traps (`get`, `set`, `has`, `apply`, `deleteProperty`, `ownKeys`) supported in the Dynamic tier (QuickJS-ng). Dynamic `any` method calls, prototype traversal, and unconstrained dynamic invocations with arbitrary argument arity are supported. |
| **Prototype Chain Manipulation** | ❌ Rejected | `Object.setPrototypeOf`, `__proto__`, `Object.defineProperty` (runtime dynamic getters/setters) are disabled to preserve static struct layouts. |

---
Expand Down
61 changes: 53 additions & 8 deletions internal/backend/llvm/dynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func moduleHasDynamic(module ir.Module) bool {

func hasDynamicInstruction(list []ir.Instruction) bool {
for _, instruction := range list {
if instruction.Op == ir.OpDynamicCall || instruction.Op == ir.OpDynamicFunctionCall || hasDynamicInstruction(instruction.Then) || hasDynamicInstruction(instruction.Else) || hasDynamicInstruction(instruction.Body) || hasDynamicInstruction(instruction.Catch) || hasDynamicInstruction(instruction.Finally) {
if instruction.Op == ir.OpDynamicCall || instruction.Op == ir.OpDynamicFunctionCall || (instruction.Op == ir.OpCall && strings.HasPrefix(instruction.Callee, "__dynamic.")) || hasDynamicInstruction(instruction.Then) || hasDynamicInstruction(instruction.Else) || hasDynamicInstruction(instruction.Body) || hasDynamicInstruction(instruction.Catch) || hasDynamicInstruction(instruction.Finally) {
return true
}
}
Expand Down Expand Up @@ -101,8 +101,8 @@ func (e *functionEmitter) emitDynamicCall(out *strings.Builder, instruction ir.I
}

func (e *functionEmitter) emitDynamicFunctionCall(out *strings.Builder, instruction ir.Instruction) error {
if len(instruction.Args) == 0 || len(instruction.Args) > 5 {
return fmt.Errorf("dynamic function call supports one callable and up to four arguments")
if len(instruction.Args) == 0 {
return fmt.Errorf("dynamic function call requires at least a callable")
}
callable := e.resolveArg(out, instruction.Args[0])
if e.types[instruction.Args[0]] == ir.TypeUnknown {
Expand All @@ -113,14 +113,25 @@ func (e *functionEmitter) emitDynamicFunctionCall(out *strings.Builder, instruct
e.loadCounter++
out.WriteString(fmt.Sprintf(" %%%s = inttoptr i64 %%%s to ptr\n", callable, payload))
}
pointers := []string{"ptr null", "ptr null", "ptr null", "ptr null"}
argCount := len(instruction.Args) - 1
arrayCount := argCount
if arrayCount == 0 {
arrayCount = 1
}
argsSlot := fmt.Sprintf("dynamic.function.args.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = alloca [%d x %s]\n", argsSlot, arrayCount, boxedLLVMType)
for i, arg := range instruction.Args[1:] {
argType := e.types[arg]
pointer, err := e.emitCanonicalValuePointer(out, arg, argType, fmt.Sprintf("dynamic.function.arg.%d", i))
if err != nil {
boxed := fmt.Sprintf("dynamic.function.arg.boxed.%d", e.loadCounter)
e.loadCounter++
if err := e.emitBoxValue(out, arg, argType, boxed); err != nil {
return err
}
pointers[i] = "ptr " + pointer
index := fmt.Sprintf("dynamic.function.arg.index.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = getelementptr inbounds [%d x %s], ptr %%%s, i64 0, i64 %d\n", index, arrayCount, boxedLLVMType, argsSlot, i)
fmt.Fprintf(out, " store %s %%%s, ptr %%%s\n", boxedLLVMType, boxed, index)
}
thisPointer := e.dynamicUndefinedValuePointer(out)
if instruction.This != "" {
Expand All @@ -135,14 +146,44 @@ func (e *functionEmitter) emitDynamicFunctionCall(out *strings.Builder, instruct
out.WriteString(fmt.Sprintf(" %%%s = alloca %s\n", outSlot, boxedLLVMType))
status := fmt.Sprintf("dynamic.function.status.%d", e.runtimeStatus)
e.runtimeStatus++
out.WriteString(fmt.Sprintf(" %%%s = call i32 @scriptgo_dynamic_invoke_function(ptr %%%s, ptr %s, i32 %d, %s, i32 %d, ptr %%%s)\n", status, callable, thisPointer, len(instruction.Args)-1, strings.Join(pointers, ", "), dynamicResultTag(instruction.Type), outSlot))
out.WriteString(fmt.Sprintf(" %%%s = call i32 @scriptgo_dynamic_invoke_function(ptr %%%s, ptr %s, i32 %d, ptr %%%s, i32 %d, ptr %%%s)\n", status, callable, thisPointer, argCount, argsSlot, dynamicResultTag(instruction.Type), outSlot))
out.WriteString(fmt.Sprintf(" call void @scriptgo_dynamic_abort_if_failed(i32 %%%s)\n", status))
boxed := fmt.Sprintf("dynamic.function.result.%d", e.loadCounter)
e.loadCounter++
out.WriteString(fmt.Sprintf(" %%%s = load %s, ptr %%%s\n", boxed, boxedLLVMType, outSlot))
return e.emitDynamicResult(out, instruction.Type, boxed, instruction.Result)
}

func (e *functionEmitter) emitDynamicIntrinsic(out *strings.Builder, instruction ir.Instruction) error {
switch instruction.Callee {
case "__dynamic.new_proxy":
if len(instruction.Args) != 2 {
return fmt.Errorf("__dynamic.new_proxy expects 2 arguments, got %d", len(instruction.Args))
}
targetSlot, err := e.emitCanonicalValuePointer(out, instruction.Args[0], e.types[instruction.Args[0]], "proxy.target")
if err != nil {
return err
}
handlerSlot, err := e.emitCanonicalValuePointer(out, instruction.Args[1], e.types[instruction.Args[1]], "proxy.handler")
if err != nil {
return err
}
outSlot := fmt.Sprintf("dynamic.proxy.out.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = alloca %s\n", outSlot, boxedLLVMType)
status := fmt.Sprintf("dynamic.proxy.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_dynamic_new_proxy(ptr %s, ptr %s, ptr %%%s)\n", status, targetSlot, handlerSlot, outSlot)
fmt.Fprintf(out, " call void @scriptgo_dynamic_abort_if_failed(i32 %%%s)\n", status)
boxedResult := fmt.Sprintf("dynamic.proxy.result.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = load %s, ptr %%%s\n", boxedResult, boxedLLVMType, outSlot)
return e.emitDynamicResult(out, instruction.Type, boxedResult, instruction.Result)
default:
return fmt.Errorf("unknown dynamic intrinsic %s", instruction.Callee)
}
}

func (e *functionEmitter) dynamicUndefinedValuePointer(out *strings.Builder) string {
slot := fmt.Sprintf("dynamic.function.undefined.this.%d", e.loadCounter)
e.loadCounter++
Expand Down Expand Up @@ -187,6 +228,8 @@ func (e *functionEmitter) emitDynamicModuleRegistry(out *strings.Builder) error

func dynamicResultTag(typ ir.Type) int {
switch typ {
case ir.TypeVoid:
return 0
case ir.TypeBool:
return 2
case ir.TypeNumber:
Expand Down Expand Up @@ -225,6 +268,8 @@ func (e *functionEmitter) emitDynamicResult(out *strings.Builder, typ ir.Type, b
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue %s %%%s, 0\n", tag, boxedLLVMType, boxed)
switch typ {
case ir.TypeVoid:
return nil
case ir.TypeUnknown:
fmt.Fprintf(out, " %%%s = load %s, ptr %%%s\n", result, boxedLLVMType, e.dynamicResultSlot(out, boxed))
case ir.TypeNumber:
Expand Down
4 changes: 3 additions & 1 deletion internal/backend/llvm/emit.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ func EmitWithOptions(module ir.Module, options Options) (string, error) {
out.WriteString("declare i32 @scriptgo_dynamic_register_module(ptr, ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_dynamic_register_dependency(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_dynamic_call_module(ptr, ptr, ptr, i32, i32, i32, ptr)\n")
out.WriteString("declare i32 @scriptgo_dynamic_invoke_function(ptr, ptr, i32, ptr, ptr, ptr, ptr, i32, ptr)\n")
out.WriteString("declare i32 @scriptgo_dynamic_invoke_function(ptr, ptr, i32, ptr, i32, ptr)\n")
out.WriteString("declare i32 @scriptgo_dynamic_new_proxy(ptr, ptr, ptr)\n")
out.WriteString("declare void @scriptgo_dynamic_abort_if_failed(i32)\n")
}
out.WriteString("declare void @scriptgo_debugger_break(ptr, i32)\n\n")
Expand Down Expand Up @@ -313,6 +314,7 @@ func EmitWithOptions(module ir.Module, options Options) (string, error) {
out.WriteString("declare i32 @scriptgo_object_property_bigint_set(ptr, ptr, i64)\n")
out.WriteString("declare i32 @scriptgo_object_property_ptr_set(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_object_property_unknown_set(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_object_delete_property(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_unknown_number_property(ptr, ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_object_type_set(ptr, ptr)\n")
out.WriteString("declare i32 @scriptgo_object_type_set_static(ptr, ptr)\n")
Expand Down
9 changes: 9 additions & 0 deletions internal/backend/llvm/instructions_calls.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ func (e *functionEmitter) emitPrint(out *strings.Builder, instruction ir.Instruc
}

func (e *functionEmitter) emitCall(out *strings.Builder, instruction ir.Instruction) error {
if strings.HasPrefix(instruction.Callee, "__dynamic.") {
if err := e.emitDynamicIntrinsic(out, instruction); err != nil {
return err
}
if instruction.Result != "" {
e.types[instruction.Result] = instruction.Type
}
return nil
}
if strings.HasPrefix(instruction.Callee, "__console.") {
if err := e.emitConsoleIntrinsic(out, instruction); err != nil {
return err
Expand Down
5 changes: 5 additions & 0 deletions internal/backend/llvm/numbers.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ func (e *functionEmitter) emitNumberIntrinsic(out *strings.Builder, instruction
bigIntF64 := instruction.Result + ".f64"
fmt.Fprintf(out, " %%%s = sitofp i64 %%%s to double\n", bigIntF64, instruction.Args[0])
fmt.Fprintf(out, " %%%s = fadd double %%%s, 0.0\n", instruction.Result, bigIntF64)
} else if argType == ir.TypeUnknown {
payload := fmt.Sprintf("number.unknown.payload.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue { i32, i32, i64, i64 } %%%s, 2\n", payload, instruction.Args[0])
fmt.Fprintf(out, " %%%s = bitcast i64 %%%s to double\n", instruction.Result, payload)
} else {
fmt.Fprintf(out, " %%%s = fadd double %%%s, 0.0\n", instruction.Result, instruction.Args[0])
}
Expand Down
18 changes: 16 additions & 2 deletions internal/backend/llvm/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,27 @@ func (e *functionEmitter) emitInstanceOf(out *strings.Builder, instruction ir.In
} else if len(instruction.Args) > 1 {
cls := instruction.Args[1]
clsVal := cls
clsType := e.types[cls]
if slot, ok := e.varSlots[cls]; ok {
loaded := fmt.Sprintf("%s.instanceof_cls.%d", cls, e.loadCounter)
e.loadCounter++
out.WriteString(fmt.Sprintf(" %%%s = load ptr, ptr %%%s\n", loaded, slot))
if clsType == ir.TypeUnknown {
out.WriteString(fmt.Sprintf(" %%%s = load { i32, i32, i64, i64 }, ptr %%%s\n", loaded, slot))
} else {
out.WriteString(fmt.Sprintf(" %%%s = load ptr, ptr %%%s\n", loaded, slot))
}
clsVal = loaded
}
classArg = "%" + clsVal
if clsType == ir.TypeUnknown {
propPayload := fmt.Sprintf("instanceof.prop.payload.%d", e.loadCounter)
propPtr := fmt.Sprintf("instanceof.prop.ptr.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue { i32, i32, i64, i64 } %%%s, 2\n", propPayload, clsVal)
fmt.Fprintf(out, " %%%s = inttoptr i64 %%%s to ptr\n", propPtr, propPayload)
classArg = "%" + propPtr
} else {
classArg = "%" + clsVal
}
} else {
return fmt.Errorf("instanceof requires target class or property")
}
Expand Down
81 changes: 73 additions & 8 deletions internal/backend/llvm/objects_intrinsics.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,21 @@ func (e *functionEmitter) emitObjectIntrinsic(out *strings.Builder, instruction
ptrObj = "%" + ptrName
}
propertyArg := e.resolveArg(out, instruction.Args[1])
ptrProperty := "%" + propertyArg
if e.types[instruction.Args[1]] == ir.TypeUnknown {
propPayload := fmt.Sprintf("dynamic.propname.payload.%d", e.loadCounter)
propPtr := fmt.Sprintf("dynamic.propname.ptr.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue { i32, i32, i64, i64 } %%%s, 2\n", propPayload, propertyArg)
fmt.Fprintf(out, " %%%s = inttoptr i64 %%%s to ptr\n", propPtr, propPayload)
ptrProperty = "%" + propPtr
}
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
e.types[instruction.Result] = ir.TypeUnknown
valueSlot := fmt.Sprintf("%s.dynamic.value.slot", instruction.Result)
fmt.Fprintf(out, " %%%s = alloca { i32, i32, i64, i64 }\n", valueSlot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_unknown_get(ptr %s, ptr %%%s, ptr %%%s)\n", status, ptrObj, propertyArg, valueSlot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_unknown_get(ptr %s, ptr %s, ptr %%%s)\n", status, ptrObj, ptrProperty, valueSlot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
fmt.Fprintf(out, " %%%s = load { i32, i32, i64, i64 }, ptr %%%s\n", instruction.Result, valueSlot)
return nil
Expand All @@ -195,6 +204,15 @@ func (e *functionEmitter) emitObjectIntrinsic(out *strings.Builder, instruction
ptrObj = ptrName
}
propertyArg := e.resolveArg(out, instruction.Args[1])
ptrProperty := "%" + propertyArg
if e.types[instruction.Args[1]] == ir.TypeUnknown {
propPayload := fmt.Sprintf("dynamic.propname.payload.%d", e.loadCounter)
propPtr := fmt.Sprintf("dynamic.propname.ptr.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue { i32, i32, i64, i64 } %%%s, 2\n", propPayload, propertyArg)
fmt.Fprintf(out, " %%%s = inttoptr i64 %%%s to ptr\n", propPtr, propPayload)
ptrProperty = "%" + propPtr
}
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
e.types[instruction.Result] = instruction.Type
Expand All @@ -207,9 +225,9 @@ func (e *functionEmitter) emitObjectIntrinsic(out *strings.Builder, instruction
if err != nil {
return err
}
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_unknown_number_property(ptr %s, ptr %%%s, ptr %%%s)\n", status, valuePtr, propertyArg, slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_unknown_number_property(ptr %s, ptr %s, ptr %%%s)\n", status, valuePtr, ptrProperty, slot)
} else {
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_number_get(ptr %%%s, ptr %%%s, ptr %%%s)\n", status, ptrObj, propertyArg, slot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_number_get(ptr %%%s, ptr %s, ptr %%%s)\n", status, ptrObj, ptrProperty, slot)
}
out.WriteString(fmt.Sprintf(" call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status))
out.WriteString(fmt.Sprintf(" %%%s = load double, ptr %%%s\n", instruction.Result, slot))
Expand Down Expand Up @@ -241,6 +259,44 @@ func (e *functionEmitter) emitObjectIntrinsic(out *strings.Builder, instruction
out.WriteString(fmt.Sprintf(" %%%s = load ptr, ptr %%%s\n", instruction.Result, slot))
}
return nil
case "__object.delete_prop":
if len(instruction.Args) != 2 {
return fmt.Errorf("__object.delete_prop requires object and property")
}
objArg := e.resolveArg(out, instruction.Args[0])
propertyArg := e.resolveArg(out, instruction.Args[1])
objType := e.types[instruction.Args[0]]
ptrObj := objArg
if objType == ir.TypeUnknown {
payloadName := fmt.Sprintf("dynamic.delete.payload.%d", e.loadCounter)
ptrName := fmt.Sprintf("dynamic.delete.ptr.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue { i32, i32, i64, i64 } %%%s, 2\n", payloadName, objArg)
fmt.Fprintf(out, " %%%s = inttoptr i64 %%%s to ptr\n", ptrName, payloadName)
ptrObj = ptrName
}
ptrProperty := propertyArg
if e.types[instruction.Args[1]] == ir.TypeUnknown {
propPayload := fmt.Sprintf("dynamic.delete.prop.payload.%d", e.loadCounter)
propPtr := fmt.Sprintf("dynamic.delete.prop.ptr.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue { i32, i32, i64, i64 } %%%s, 2\n", propPayload, propertyArg)
fmt.Fprintf(out, " %%%s = inttoptr i64 %%%s to ptr\n", propPtr, propPayload)
ptrProperty = propPtr
}
outSlot := fmt.Sprintf("delete.prop.out.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = alloca i32\n", outSlot)
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_delete_property(ptr %%%s, ptr %%%s, ptr %%%s)\n", status, ptrObj, ptrProperty, outSlot)
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
i32Val := fmt.Sprintf("delete.prop.val.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = load i32, ptr %%%s\n", i32Val, outSlot)
fmt.Fprintf(out, " %%%s = trunc i32 %%%s to i1\n", instruction.Result, i32Val)
e.types[instruction.Result] = ir.TypeBool
return nil
case "__object.set_prop":
if len(instruction.Args) != 3 {
return fmt.Errorf("__object.set_prop requires object, property, and value")
Expand All @@ -258,21 +314,30 @@ func (e *functionEmitter) emitObjectIntrinsic(out *strings.Builder, instruction
fmt.Fprintf(out, " %%%s = inttoptr i64 %%%s to ptr\n", ptrName, payloadName)
ptrObj = ptrName
}
ptrProperty := propertyArg
if e.types[instruction.Args[1]] == ir.TypeUnknown {
propPayload := fmt.Sprintf("dynamic.set.prop.payload.%d", e.loadCounter)
propPtr := fmt.Sprintf("dynamic.set.prop.ptr.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = extractvalue { i32, i32, i64, i64 } %%%s, 2\n", propPayload, propertyArg)
fmt.Fprintf(out, " %%%s = inttoptr i64 %%%s to ptr\n", propPtr, propPayload)
ptrProperty = propPtr
}
valueType := e.types[instruction.Args[2]]
status := fmt.Sprintf("runtime.status.%d", e.runtimeStatus)
e.runtimeStatus++
switch valueType {
case ir.TypeString:
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_string_set(ptr %%%s, ptr %%%s, ptr %%%s)\n", status, ptrObj, propertyArg, valueArg)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_string_set(ptr %%%s, ptr %%%s, ptr %%%s)\n", status, ptrObj, ptrProperty, valueArg)
case ir.TypeNumber:
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_number_set(ptr %%%s, ptr %%%s, double %%%s)\n", status, ptrObj, propertyArg, valueArg)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_number_set(ptr %%%s, ptr %%%s, double %%%s)\n", status, ptrObj, ptrProperty, valueArg)
case ir.TypeBool:
boolValue := fmt.Sprintf("dynamic.set.bool.%d", e.loadCounter)
e.loadCounter++
fmt.Fprintf(out, " %%%s = zext i1 %%%s to i32\n", boolValue, valueArg)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_bool_set(ptr %%%s, ptr %%%s, i32 %%%s)\n", status, ptrObj, propertyArg, boolValue)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_bool_set(ptr %%%s, ptr %%%s, i32 %%%s)\n", status, ptrObj, ptrProperty, boolValue)
case ir.TypeBigInt:
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_bigint_set(ptr %%%s, ptr %%%s, i64 %%%s)\n", status, ptrObj, propertyArg, valueArg)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_bigint_set(ptr %%%s, ptr %%%s, i64 %%%s)\n", status, ptrObj, ptrProperty, valueArg)
default:
boxed := valueArg
if valueType != ir.TypeUnknown {
Expand All @@ -286,7 +351,7 @@ func (e *functionEmitter) emitObjectIntrinsic(out *strings.Builder, instruction
e.loadCounter++
fmt.Fprintf(out, " %%%s = alloca { i32, i32, i64, i64 }\n", boxedSlot)
fmt.Fprintf(out, " store { i32, i32, i64, i64 } %%%s, ptr %%%s\n", boxed, boxedSlot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_unknown_set(ptr %%%s, ptr %%%s, ptr %%%s)\n", status, ptrObj, propertyArg, boxedSlot)
fmt.Fprintf(out, " %%%s = call i32 @scriptgo_object_property_unknown_set(ptr %%%s, ptr %%%s, ptr %%%s)\n", status, ptrObj, ptrProperty, boxedSlot)
}
fmt.Fprintf(out, " call void @scriptgo_runtime_abort_if_failed(i32 %%%s)\n", status)
return nil
Expand Down
Loading
Loading