@@ -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,235 @@ 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 -> " 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
+ | Float16 ->
1489
+ box
1490
+ (return
1491
+ (W. Call
1492
+ (f, ta :: ofs :: (if size = 0 then [] else [ W. GlobalGet little_endian ]))))
1493
+ | Complex32 | Complex64 ->
1494
+ let delta = Int32. shift_left 1l (size - 1 ) in
1495
+ let * ofs' = Arith. (return ofs + const delta) in
1496
+ let * x = box (return (W. Call (f, [ ta; ofs; W. GlobalGet little_endian ]))) in
1497
+ let * y = box (return (W. Call (f, [ ta; ofs'; W. GlobalGet little_endian ]))) in
1498
+ let * ty = Type. float_array_type in
1499
+ return (W. ArrayNewFixed (ty, [ x; y ]))
1500
+
1501
+ let set_at_offset ~kind a i v =
1502
+ let name, (typ : Wasm_ast.value_type ), size, unbox =
1503
+ match (kind : Typing.Bigarray.kind ) with
1504
+ | Float32 ->
1505
+ ( " dv_set_f32"
1506
+ , F32
1507
+ , 2
1508
+ , fun x ->
1509
+ let * x = x in
1510
+ return (W. F32DemoteF64 x) )
1511
+ | Float64 -> " dv_set_f64" , F64 , 3 , Fun. id
1512
+ | Int8_signed | Int8_unsigned -> " dv_set_i8" , I32 , 0 , Fun. id
1513
+ | Int16_signed | Int16_unsigned -> " dv_set_i16" , I32 , 1 , Fun. id
1514
+ | Int32 -> " dv_set_i32" , I32 , 2 , Fun. id
1515
+ | Nativeint -> " dv_set_i32" , I32 , 2 , Fun. id
1516
+ | Int64 -> " dv_set_i64" , I64 , 3 , Fun. id
1517
+ | Int -> " dv_set_i32" , I32 , 2 , Fun. id
1518
+ | Float16 ->
1519
+ ( " dv_set_i16"
1520
+ , I32
1521
+ , 1
1522
+ , fun x ->
1523
+ let * conv =
1524
+ register_import
1525
+ ~name: " caml_double_to_float16"
1526
+ (Fun { W. params = [ F64 ]; result = [ I32 ] })
1527
+ in
1528
+ let * x = Fun. id x in
1529
+ return (W. Call (conv, [ x ])) )
1530
+ | Complex32 ->
1531
+ ( " dv_set_f32"
1532
+ , F32
1533
+ , 3
1534
+ , fun x ->
1535
+ let * x = x in
1536
+ return (W. F32DemoteF64 x) )
1537
+ | Complex64 -> " dv_set_f64" , F64 , 4 , Fun. id
1538
+ in
1539
+ let * ty = Type. bigarray_type in
1540
+ let * ta = Memory. wasm_struct_get ty (Memory. wasm_cast ty a) 2 in
1541
+ let * ofs = Arith. (i lsl const (Int32. of_int size)) in
1542
+ let * little_endian =
1543
+ register_import
1544
+ ~import_module: " bindings"
1545
+ ~name: " littleEndian"
1546
+ (Global { mut = false ; typ = I32 })
1547
+ in
1548
+ let * f =
1549
+ register_import
1550
+ ~import_module: " bindings"
1551
+ ~name
1552
+ (Fun
1553
+ { W. params =
1554
+ Ref { nullable = true ; typ = Extern }
1555
+ :: I32
1556
+ :: typ
1557
+ :: (if size = 0 then [] else [ I32 ])
1558
+ ; result = []
1559
+ })
1560
+ in
1561
+ match kind with
1562
+ | Float32
1563
+ | Float64
1564
+ | Int8_signed
1565
+ | Int8_unsigned
1566
+ | Int16_signed
1567
+ | Int16_unsigned
1568
+ | Int32
1569
+ | Int64
1570
+ | Int
1571
+ | Nativeint
1572
+ | Float16 ->
1573
+ let * v = unbox v in
1574
+ instr
1575
+ (W. CallInstr
1576
+ ( f
1577
+ , ta :: ofs :: v :: (if size = 0 then [] else [ W. GlobalGet little_endian ])
1578
+ ))
1579
+ | Complex32 | Complex64 ->
1580
+ let delta = Int32. shift_left 1l (size - 1 ) in
1581
+ let * ofs' = Arith. (return ofs + const delta) in
1582
+ let ty = Type. float_array_type in
1583
+ let * x = unbox (Memory. wasm_array_get ~ty v (Arith. const 0l )) in
1584
+ let * () = instr (W. CallInstr (f, [ ta; ofs; x; W. GlobalGet little_endian ])) in
1585
+ let * y = unbox (Memory. wasm_array_get ~ty v (Arith. const 1l )) in
1586
+ instr (W. CallInstr (f, [ ta; ofs'; y; W. GlobalGet little_endian ]))
1587
+
1588
+ let offset ~bound_error_index ~(layout : Typing.Bigarray.layout ) ta ~indices =
1589
+ let l =
1590
+ List. mapi
1591
+ ~f: (fun pos i ->
1592
+ let i =
1593
+ match layout with
1594
+ | C -> i
1595
+ | Fortran -> Arith. (i - const 1l )
1596
+ in
1597
+ let i' = Code.Var. fresh () in
1598
+ let dim = Code.Var. fresh () in
1599
+ ( (let * () = store ~typ: I32 i' i in
1600
+ let * () = store ~typ: I32 dim (dimension pos ta) in
1601
+ let * cond = Arith. uge (load i') (load dim) in
1602
+ instr (W. Br_if (bound_error_index, cond)))
1603
+ , i'
1604
+ , dim ))
1605
+ indices
1606
+ in
1607
+ let l =
1608
+ match layout with
1609
+ | C -> l
1610
+ | Fortran -> List. rev l
1611
+ in
1612
+ match l with
1613
+ | (instrs , i' , _ ) :: rem ->
1614
+ List. fold_left
1615
+ ~f: (fun (instrs , ofs ) (instrs' , i' , dim ) ->
1616
+ let ofs' = Code.Var. fresh () in
1617
+ ( (let * () = instrs in
1618
+ let * () = instrs' in
1619
+ store ~typ: I32 ofs' Arith. ((ofs * load dim) + load i'))
1620
+ , load ofs' ))
1621
+ ~init: (instrs, load i')
1622
+ rem
1623
+ | [] -> return () , Arith. const 0l
1624
+
1625
+ let get ~bound_error_index ~kind ~layout ta ~indices =
1626
+ let instrs, ofs = offset ~bound_error_index ~layout ta ~indices in
1627
+ seq instrs (get_at_offset ~kind ta ofs)
1628
+
1629
+ let set ~bound_error_index ~kind ~layout ta ~indices v =
1630
+ let instrs, ofs = offset ~bound_error_index ~layout ta ~indices in
1631
+ seq
1632
+ (let * () = instrs in
1633
+ set_at_offset ~kind ta ofs v)
1634
+ Value. unit
1635
+ end
1636
+
1376
1637
module JavaScript = struct
1377
1638
let anyref = W. Ref { nullable = true ; typ = Any }
1378
1639
0 commit comments