Skip to content

Commit 8e19f3c

Browse files
committed
Bigarrays
1 parent d5ae284 commit 8e19f3c

File tree

7 files changed

+612
-78
lines changed

7 files changed

+612
-78
lines changed

compiler/lib-wasm/code_generation.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ module Arith = struct
368368
(match e, e' with
369369
| W.Const (I32 n), W.Const (I32 n') when Int32.(n' < 31l) ->
370370
W.Const (I32 (Int32.shift_left n (Int32.to_int n')))
371+
| _, W.Const (I32 0l) -> e
371372
| _ -> W.BinOp (I32 Shl, e, e'))
372373

373374
let ( lsr ) = binary (Shr U)

compiler/lib-wasm/gc_target.ml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,38 @@ module Type = struct
419419
}
420420
])
421421
})
422+
423+
let int_array_type =
424+
register_type "int_array" (fun () ->
425+
return
426+
{ supertype = None
427+
; final = true
428+
; typ = W.Array { mut = true; typ = Value I32 }
429+
})
430+
431+
let bigarray_type =
432+
register_type "bigarray" (fun () ->
433+
let* custom_operations = custom_operations_type in
434+
let* int_array = int_array_type in
435+
let* custom = custom_type in
436+
return
437+
{ supertype = Some custom
438+
; final = true
439+
; typ =
440+
W.Struct
441+
[ { mut = false
442+
; typ = Value (Ref { nullable = false; typ = Type custom_operations })
443+
}
444+
; { mut = true; typ = Value (Ref { nullable = false; typ = Extern }) }
445+
; { mut = true; typ = Value (Ref { nullable = false; typ = Extern }) }
446+
; { mut = false
447+
; typ = Value (Ref { nullable = false; typ = Type int_array })
448+
}
449+
; { mut = false; typ = Packed I8 }
450+
; { mut = false; typ = Packed I8 }
451+
; { mut = false; typ = Packed I8 }
452+
]
453+
})
422454
end
423455

424456
module Value = struct
@@ -1360,6 +1392,107 @@ module Math = struct
13601392
let exp2 x = power (return (W.Const (F64 2.))) x
13611393
end
13621394

1395+
module Bigarray = struct
1396+
let dim n a =
1397+
let* ty = Type.bigarray_type in
1398+
Memory.wasm_array_get
1399+
~ty:Type.int_array_type
1400+
(Memory.wasm_struct_get ty (Memory.wasm_cast ty a) 3)
1401+
(Arith.const (Int32.of_int n))
1402+
1403+
let get ~kind a i =
1404+
let name, (typ : Wasm_ast.value_type), size, box =
1405+
match (kind : Typing.Bigarray.kind) with
1406+
| Float32 ->
1407+
( "dv_get_f32"
1408+
, F32
1409+
, 2
1410+
, fun x ->
1411+
let* x = x in
1412+
Memory.box_float (return (W.F64PromoteF32 x)) )
1413+
| Float64 -> "dv_get_f64", F64, 3, Memory.box_float
1414+
| Int8_signed -> "dv_get_i8", I32, 0, Fun.id
1415+
| Int8_unsigned | Char -> "dv_get_ui8", I32, 0, Fun.id
1416+
| Int16_signed -> "dv_get_i16", I32, 1, Fun.id
1417+
| Int16_unsigned -> "dv_get_ui16", I32, 1, Fun.id
1418+
| Int32 -> "dv_get_i32", I32, 2, Memory.box_int32
1419+
| Nativeint -> "dv_get_i32", I32, 2, Memory.box_nativeint
1420+
| Int64 -> "dv_get_i64", I64, 3, Memory.box_int64
1421+
| Int -> "dv_get_i32", I32, 2, Fun.id
1422+
| Complex32 | Complex64 | Float16 -> assert false (*ZZZ*)
1423+
in
1424+
let* little_endian =
1425+
register_import
1426+
~import_module:"bindings"
1427+
~name:"littleEndian"
1428+
(Global { mut = false; typ = I32 })
1429+
in
1430+
let* f =
1431+
register_import
1432+
~import_module:"bindings"
1433+
~name
1434+
(Fun
1435+
{ W.params =
1436+
Ref { nullable = true; typ = Extern }
1437+
:: I32
1438+
:: (if size = 0 then [] else [ I32 ])
1439+
; result = [ typ ]
1440+
})
1441+
in
1442+
let* ty = Type.bigarray_type in
1443+
let* ta = Memory.wasm_struct_get ty (Memory.wasm_cast ty a) 2 in
1444+
let* ofs = Arith.(i lsl const (Int32.of_int size)) in
1445+
box
1446+
(return
1447+
(W.Call (f, ta :: ofs :: (if size = 0 then [] else [ W.GlobalGet little_endian ]))))
1448+
1449+
let set ~kind a i v =
1450+
let name, (typ : Wasm_ast.value_type), size, unbox =
1451+
match (kind : Typing.Bigarray.kind) with
1452+
| Float32 ->
1453+
( "dv_set_f32"
1454+
, F32
1455+
, 2
1456+
, fun x ->
1457+
let* e = Memory.unbox_float x in
1458+
return (W.F32DemoteF64 e) )
1459+
| Float64 -> "dv_set_f64", F64, 3, Memory.unbox_float
1460+
| Int8_signed | Int8_unsigned | Char -> "dv_set_i8", I32, 0, Fun.id
1461+
| Int16_signed | Int16_unsigned -> "dv_set_i16", I32, 1, Fun.id
1462+
| Int32 -> "dv_set_i32", I32, 2, Memory.unbox_int32
1463+
| Nativeint -> "dv_set_i32", I32, 2, Memory.unbox_nativeint
1464+
| Int64 -> "dv_set_i64", I64, 3, Memory.unbox_int64
1465+
| Int -> "dv_set_i32", I32, 2, Fun.id
1466+
| Complex32 | Complex64 | Float16 -> assert false (*ZZZ*)
1467+
in
1468+
let* ty = Type.bigarray_type in
1469+
let* ta = Memory.wasm_struct_get ty (Memory.wasm_cast ty a) 2 in
1470+
let* ofs = Arith.(i lsl const (Int32.of_int size)) in
1471+
let* v = unbox v in
1472+
let* little_endian =
1473+
register_import
1474+
~import_module:"bindings"
1475+
~name:"littleEndian"
1476+
(Global { mut = false; typ = I32 })
1477+
in
1478+
let* f =
1479+
register_import
1480+
~import_module:"bindings"
1481+
~name
1482+
(Fun
1483+
{ W.params =
1484+
Ref { nullable = true; typ = Extern }
1485+
:: I32
1486+
:: typ
1487+
:: (if size = 0 then [] else [ I32 ])
1488+
; result = []
1489+
})
1490+
in
1491+
instr
1492+
(W.CallInstr
1493+
(f, ta :: ofs :: v :: (if size = 0 then [] else [ W.GlobalGet little_endian ])))
1494+
end
1495+
13631496
module JavaScript = struct
13641497
let anyref = W.Ref { nullable = true; typ = Any }
13651498

0 commit comments

Comments
 (0)