@@ -430,6 +430,38 @@ module Type = struct
430
430
}
431
431
])
432
432
})
433
+
434
+ let int_array_type =
435
+ register_type " int_array" (fun () ->
436
+ return
437
+ { supertype = None
438
+ ; final = true
439
+ ; typ = W. Array { mut = true ; typ = Value I32 }
440
+ })
441
+
442
+ let bigarray_type =
443
+ register_type " bigarray" (fun () ->
444
+ let * custom_operations = custom_operations_type in
445
+ let * int_array = int_array_type in
446
+ let * custom = custom_type in
447
+ return
448
+ { supertype = Some custom
449
+ ; final = true
450
+ ; typ =
451
+ W. Struct
452
+ [ { mut = false
453
+ ; typ = Value (Ref { nullable = false ; typ = Type custom_operations })
454
+ }
455
+ ; { mut = true ; typ = Value (Ref { nullable = false ; typ = Extern }) }
456
+ ; { mut = true ; typ = Value (Ref { nullable = false ; typ = Extern }) }
457
+ ; { mut = false
458
+ ; typ = Value (Ref { nullable = false ; typ = Type int_array })
459
+ }
460
+ ; { mut = false ; typ = Packed I8 }
461
+ ; { mut = false ; typ = Packed I8 }
462
+ ; { mut = false ; typ = Packed I8 }
463
+ ]
464
+ })
433
465
end
434
466
435
467
module Value = struct
@@ -1373,6 +1405,237 @@ module Math = struct
1373
1405
let exp2 x = power (return (W. Const (F64 2. ))) x
1374
1406
end
1375
1407
1408
+ module Bigarray = struct
1409
+ let dimension n a =
1410
+ let * ty = Type. bigarray_type in
1411
+ Memory. wasm_array_get
1412
+ ~ty: Type. int_array_type
1413
+ (Memory. wasm_struct_get ty (Memory. wasm_cast ty a) 3 )
1414
+ (Arith. const (Int32. of_int n))
1415
+
1416
+ let get_at_offset ~(kind : Typing.Bigarray.kind ) a i =
1417
+ let name, (typ : Wasm_ast.value_type ), size, box =
1418
+ match kind with
1419
+ | Float32 ->
1420
+ ( " dv_get_f32"
1421
+ , F32
1422
+ , 2
1423
+ , fun x ->
1424
+ let * x = x in
1425
+ return (W. F64PromoteF32 x) )
1426
+ | Float64 -> " dv_get_f64" , F64 , 3 , Fun. id
1427
+ | Int8_signed -> " dv_get_i8" , I32 , 0 , Fun. id
1428
+ | Int8_unsigned | Char -> " dv_get_ui8" , I32 , 0 , Fun. id
1429
+ | Int16_signed -> " dv_get_i16" , I32 , 1 , Fun. id
1430
+ | Int16_unsigned -> " dv_get_ui16" , I32 , 1 , Fun. id
1431
+ | Int32 -> " dv_get_i32" , I32 , 2 , Fun. id
1432
+ | Nativeint -> " dv_get_i32" , I32 , 2 , Fun. id
1433
+ | Int64 -> " dv_get_i64" , I64 , 3 , Fun. id
1434
+ | Int -> " dv_get_i32" , I32 , 2 , Fun. id
1435
+ | Float16 ->
1436
+ ( " dv_get_i16"
1437
+ , I32
1438
+ , 1
1439
+ , fun x ->
1440
+ let * conv =
1441
+ register_import
1442
+ ~name: " caml_float16_to_double"
1443
+ (Fun { W. params = [ I32 ]; result = [ F64 ] })
1444
+ in
1445
+ let * x = x in
1446
+ return (W. Call (conv, [ x ])) )
1447
+ | Complex32 ->
1448
+ ( " dv_get_f32"
1449
+ , F32
1450
+ , 3
1451
+ , fun x ->
1452
+ let * x = x in
1453
+ return (W. F64PromoteF32 x) )
1454
+ | Complex64 -> " dv_get_f64" , F64 , 4 , Fun. id
1455
+ in
1456
+ let * little_endian =
1457
+ register_import
1458
+ ~import_module: " bindings"
1459
+ ~name: " littleEndian"
1460
+ (Global { mut = false ; typ = I32 })
1461
+ in
1462
+ let * f =
1463
+ register_import
1464
+ ~import_module: " bindings"
1465
+ ~name
1466
+ (Fun
1467
+ { W. params =
1468
+ Ref { nullable = true ; typ = Extern }
1469
+ :: I32
1470
+ :: (if size = 0 then [] else [ I32 ])
1471
+ ; result = [ typ ]
1472
+ })
1473
+ in
1474
+ let * ty = Type. bigarray_type in
1475
+ let * ta = Memory. wasm_struct_get ty (Memory. wasm_cast ty a) 2 in
1476
+ let * ofs = Arith. (i lsl const (Int32. of_int size)) in
1477
+ match kind with
1478
+ | Float32
1479
+ | Float64
1480
+ | Int8_signed
1481
+ | Int8_unsigned
1482
+ | Int16_signed
1483
+ | Int16_unsigned
1484
+ | Int32
1485
+ | Int64
1486
+ | Int
1487
+ | Nativeint
1488
+ | Char
1489
+ | Float16 ->
1490
+ box
1491
+ (return
1492
+ (W. Call
1493
+ (f, ta :: ofs :: (if size = 0 then [] else [ W. GlobalGet little_endian ]))))
1494
+ | Complex32 | Complex64 ->
1495
+ let delta = Int32. shift_left 1l (size - 1 ) in
1496
+ let * ofs' = Arith. (return ofs + const delta) in
1497
+ let * x = box (return (W. Call (f, [ ta; ofs; W. GlobalGet little_endian ]))) in
1498
+ let * y = box (return (W. Call (f, [ ta; ofs'; W. GlobalGet little_endian ]))) in
1499
+ let * ty = Type. float_array_type in
1500
+ return (W. ArrayNewFixed (ty, [ x; y ]))
1501
+
1502
+ let set_at_offset ~kind a i v =
1503
+ let name, (typ : Wasm_ast.value_type ), size, unbox =
1504
+ match (kind : Typing.Bigarray.kind ) with
1505
+ | Float32 ->
1506
+ ( " dv_set_f32"
1507
+ , F32
1508
+ , 2
1509
+ , fun x ->
1510
+ let * x = x in
1511
+ return (W. F32DemoteF64 x) )
1512
+ | Float64 -> " dv_set_f64" , F64 , 3 , Fun. id
1513
+ | Int8_signed | Int8_unsigned | Char -> " dv_set_i8" , I32 , 0 , Fun. id
1514
+ | Int16_signed | Int16_unsigned -> " dv_set_i16" , I32 , 1 , Fun. id
1515
+ | Int32 -> " dv_set_i32" , I32 , 2 , Fun. id
1516
+ | Nativeint -> " dv_set_i32" , I32 , 2 , Fun. id
1517
+ | Int64 -> " dv_set_i64" , I64 , 3 , Fun. id
1518
+ | Int -> " dv_set_i32" , I32 , 2 , Fun. id
1519
+ | Float16 ->
1520
+ ( " dv_set_i16"
1521
+ , I32
1522
+ , 1
1523
+ , fun x ->
1524
+ let * conv =
1525
+ register_import
1526
+ ~name: " caml_double_to_float16"
1527
+ (Fun { W. params = [ F64 ]; result = [ I32 ] })
1528
+ in
1529
+ let * x = Fun. id x in
1530
+ return (W. Call (conv, [ x ])) )
1531
+ | Complex32 ->
1532
+ ( " dv_set_f32"
1533
+ , F32
1534
+ , 3
1535
+ , fun x ->
1536
+ let * x = x in
1537
+ return (W. F32DemoteF64 x) )
1538
+ | Complex64 -> " dv_set_f64" , F64 , 4 , Fun. id
1539
+ in
1540
+ let * ty = Type. bigarray_type in
1541
+ let * ta = Memory. wasm_struct_get ty (Memory. wasm_cast ty a) 2 in
1542
+ let * ofs = Arith. (i lsl const (Int32. of_int size)) in
1543
+ let * little_endian =
1544
+ register_import
1545
+ ~import_module: " bindings"
1546
+ ~name: " littleEndian"
1547
+ (Global { mut = false ; typ = I32 })
1548
+ in
1549
+ let * f =
1550
+ register_import
1551
+ ~import_module: " bindings"
1552
+ ~name
1553
+ (Fun
1554
+ { W. params =
1555
+ Ref { nullable = true ; typ = Extern }
1556
+ :: I32
1557
+ :: typ
1558
+ :: (if size = 0 then [] else [ I32 ])
1559
+ ; result = []
1560
+ })
1561
+ in
1562
+ match kind with
1563
+ | Float32
1564
+ | Float64
1565
+ | Int8_signed
1566
+ | Int8_unsigned
1567
+ | Int16_signed
1568
+ | Int16_unsigned
1569
+ | Int32
1570
+ | Int64
1571
+ | Int
1572
+ | Nativeint
1573
+ | Char
1574
+ | Float16 ->
1575
+ let * v = unbox v in
1576
+ instr
1577
+ (W. CallInstr
1578
+ ( f
1579
+ , ta :: ofs :: v :: (if size = 0 then [] else [ W. GlobalGet little_endian ])
1580
+ ))
1581
+ | Complex32 | Complex64 ->
1582
+ let delta = Int32. shift_left 1l (size - 1 ) in
1583
+ let * ofs' = Arith. (return ofs + const delta) in
1584
+ let ty = Type. float_array_type in
1585
+ let * x = unbox (Memory. wasm_array_get ~ty v (Arith. const 0l )) in
1586
+ let * () = instr (W. CallInstr (f, [ ta; ofs; x; W. GlobalGet little_endian ])) in
1587
+ let * y = unbox (Memory. wasm_array_get ~ty v (Arith. const 1l )) in
1588
+ instr (W. CallInstr (f, [ ta; ofs'; y; W. GlobalGet little_endian ]))
1589
+
1590
+ let offset ~bound_error_index ~(layout : Typing.Bigarray.layout ) ta ~indices =
1591
+ let l =
1592
+ List. mapi
1593
+ ~f: (fun pos i ->
1594
+ let i =
1595
+ match layout with
1596
+ | C -> i
1597
+ | Fortran -> Arith. (i - const 1l )
1598
+ in
1599
+ let i' = Code.Var. fresh () in
1600
+ let dim = Code.Var. fresh () in
1601
+ ( (let * () = store ~typ: I32 i' i in
1602
+ let * () = store ~typ: I32 dim (dimension pos ta) in
1603
+ let * cond = Arith. uge (load i') (load dim) in
1604
+ instr (W. Br_if (bound_error_index, cond)))
1605
+ , i'
1606
+ , dim ))
1607
+ indices
1608
+ in
1609
+ let l =
1610
+ match layout with
1611
+ | C -> l
1612
+ | Fortran -> List. rev l
1613
+ in
1614
+ match l with
1615
+ | (instrs , i' , _ ) :: rem ->
1616
+ List. fold_left
1617
+ ~f: (fun (instrs , ofs ) (instrs' , i' , dim ) ->
1618
+ let ofs' = Code.Var. fresh () in
1619
+ ( (let * () = instrs in
1620
+ let * () = instrs' in
1621
+ store ~typ: I32 ofs' Arith. ((ofs * load dim) + load i'))
1622
+ , load ofs' ))
1623
+ ~init: (instrs, load i')
1624
+ rem
1625
+ | [] -> return () , Arith. const 0l
1626
+
1627
+ let get ~bound_error_index ~kind ~layout ta ~indices =
1628
+ let instrs, ofs = offset ~bound_error_index ~layout ta ~indices in
1629
+ seq instrs (get_at_offset ~kind ta ofs)
1630
+
1631
+ let set ~bound_error_index ~kind ~layout ta ~indices v =
1632
+ let instrs, ofs = offset ~bound_error_index ~layout ta ~indices in
1633
+ seq
1634
+ (let * () = instrs in
1635
+ set_at_offset ~kind ta ofs v)
1636
+ Value. unit
1637
+ end
1638
+
1376
1639
module JavaScript = struct
1377
1640
let anyref = W. Ref { nullable = true ; typ = Any }
1378
1641
0 commit comments