"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/onyx",
- "args": ["-verbose", "progs/odin_example.onyx"],
+ "args": ["-verbose", "progs/simd_test.onyx"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
-RELEASE=1
+RELEASE=0
OBJ_FILES=\
build/onyxlex.o \
Basic_Kind_F64,
Basic_Kind_Rawptr,
+
+ Basic_Kind_I8X16,
+ Basic_Kind_I16X8,
+ Basic_Kind_I32X4,
+ Basic_Kind_I64X2,
+ Basic_Kind_F32X4,
+ Basic_Kind_F64X2,
};
enum BasicFlag {
Basic_Flag_Float = BH_BIT(3),
Basic_Flag_Pointer = BH_BIT(4),
+ Basic_Flag_SIMD = BH_BIT(5),
+
Basic_Flag_Numeric = Basic_Flag_Integer | Basic_Flag_Float,
Basic_Flag_Ordered = Basic_Flag_Integer | Basic_Flag_Float | Basic_Flag_Pointer,
Basic_Flag_Constant_Type = Basic_Flag_Boolean | Basic_Flag_Numeric | Basic_Flag_Pointer,
typedef u8 WasmType;
-extern const WasmType WASM_TYPE_INT32;
-extern const WasmType WASM_TYPE_INT64;
-extern const WasmType WASM_TYPE_FLOAT32;
-extern const WasmType WASM_TYPE_FLOAT64;
-
typedef struct WasmFuncType {
// NOTE: For now, WASM only allows for 1 return value.
// This may be lifted in the future.
typedef struct BranchTable {
u32 count;
u32 default_case;
- u32 cases[];
+ u32 cases[];
} BranchTable;
#define LOCAL_IS_WASM 0x8000000000000
typedef struct LocalAllocator {
u32 param_count;
- u32 allocated[4];
- u32 freed[4];
+ u32 allocated[5];
+ u32 freed[5];
i32 max_stack;
i32 curr_stack;
- match: '\b(bool|void|i8|u8|i16|u16|i32|u32|i64|u64|f32|f64|rawptr)\b'
scope: keyword.control.onyx
+ - match: '\b(i8x16|i16x8|i32x4|i64x2|f32x4|f64x2)\b'
+ scope: keyword.control.onyx
+
- match: '\b(true|false|null|context)\b'
scope: constant.numeric.onyx
- match: '\*/'
pop: true
- match: '/\*'
- push: block_comment
\ No newline at end of file
+ push: block_comment
syn keyword onyxType f32
syn keyword onyxType f64
syn keyword onyxType rawptr
+syn keyword onyxType i8x16
+syn keyword onyxType i16x8
+syn keyword onyxType i32x4
+syn keyword onyxType i64x2
+syn keyword onyxType f32x4
+syn keyword onyxType f64x2
syn keyword onyxConstant true false null
--- /dev/null
+package main
+
+#include_file "core/std/wasi"
+
+use package core
+use package simd
+
+main :: proc (args: [] cstring) {
+ x : i32x4;
+}
AstBasicType basic_type_f64 = { Ast_Kind_Basic_Type, 0, NULL, "f64" , &basic_types[Basic_Kind_F64] };
AstBasicType basic_type_rawptr = { Ast_Kind_Basic_Type, 0, NULL, "rawptr", &basic_types[Basic_Kind_Rawptr] };
+static OnyxToken simd_token = { Token_Type_Symbol, 14, "simd intrinsic", { 0 } };
+AstBasicType basic_type_i8x16 = { Ast_Kind_Basic_Type, 0, &simd_token, "i8x16", &basic_types[Basic_Kind_I8X16] };
+AstBasicType basic_type_i16x8 = { Ast_Kind_Basic_Type, 0, &simd_token, "i16x8", &basic_types[Basic_Kind_I16X8] };
+AstBasicType basic_type_i32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, "i32x4", &basic_types[Basic_Kind_I32X4] };
+AstBasicType basic_type_i64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, "i64x2", &basic_types[Basic_Kind_I64X2] };
+AstBasicType basic_type_f32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, "f32x4", &basic_types[Basic_Kind_F32X4] };
+AstBasicType basic_type_f64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, "f64x2", &basic_types[Basic_Kind_F64X2] };
+
static OnyxToken builtin_package_token = { Token_Type_Symbol, 7, "builtin ", { 0 } };
AstNode builtin_package_node = { Ast_Kind_Symbol, Ast_Flag_No_Clone, &builtin_package_token, NULL };
{ NULL, "f64", (AstNode *) &basic_type_f64 },
{ NULL, "rawptr", (AstNode *) &basic_type_rawptr },
+ { "simd", "i8x16", (AstNode *) &basic_type_i8x16 },
+ { "simd", "i16x8", (AstNode *) &basic_type_i16x8 },
+ { "simd", "i32x4", (AstNode *) &basic_type_i32x4 },
+ { "simd", "i64x2", (AstNode *) &basic_type_i64x2 },
+ { "simd", "f32x4", (AstNode *) &basic_type_f32x4 },
+ { "simd", "f64x2", (AstNode *) &basic_type_f64x2 },
+
{ "builtin", "__heap_start", (AstNode *) &builtin_heap_start },
{ "builtin", "__stack_top", (AstNode *) &builtin_stack_top },
// NOTE: These have to be in the same order as Basic
Type basic_types[] = {
- { Type_Kind_Basic, 0, { Basic_Kind_Void, 0, 0, 1, "void" } },
-
- { Type_Kind_Basic, 0, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, 1, "bool" } },
-
- { Type_Kind_Basic, 0, { Basic_Kind_I8, Basic_Flag_Integer, 1, 1, "i8" } },
- { Type_Kind_Basic, 0, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, 1, "u8" } },
- { Type_Kind_Basic, 0, { Basic_Kind_I16, Basic_Flag_Integer, 2, 2, "i16" } },
- { Type_Kind_Basic, 0, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, 2, "u16" } },
- { Type_Kind_Basic, 0, { Basic_Kind_I32, Basic_Flag_Integer, 4, 4, "i32" } },
- { Type_Kind_Basic, 0, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, 4, "u32" } },
- { Type_Kind_Basic, 0, { Basic_Kind_I64, Basic_Flag_Integer, 8, 8, "i64" } },
- { Type_Kind_Basic, 0, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, 8, "u64" } },
-
- { Type_Kind_Basic, 0, { Basic_Kind_F32, Basic_Flag_Float, 4, 4, "f32" } },
- { Type_Kind_Basic, 0, { Basic_Kind_F64, Basic_Flag_Float, 8, 4, "f64" } },
-
- { Type_Kind_Basic, 0, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 4, 4, "rawptr" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_Void, 0, 0, 1, "void" } },
+
+ { Type_Kind_Basic, 0, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, 1, "bool" } },
+
+ { Type_Kind_Basic, 0, { Basic_Kind_I8, Basic_Flag_Integer, 1, 1, "i8" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, 1, "u8" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I16, Basic_Flag_Integer, 2, 2, "i16" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, 2, "u16" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I32, Basic_Flag_Integer, 4, 4, "i32" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, 4, "u32" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I64, Basic_Flag_Integer, 8, 8, "i64" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, 8, "u64" } },
+
+ { Type_Kind_Basic, 0, { Basic_Kind_F32, Basic_Flag_Float, 4, 4, "f32" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_F64, Basic_Flag_Float, 8, 4, "f64" } },
+
+ { Type_Kind_Basic, 0, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 4, 4, "rawptr" } },
+
+ { Type_Kind_Basic, 0, { Basic_Kind_I8X16, Basic_Flag_SIMD, 16, 16, "i8x16" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I16X8, Basic_Flag_SIMD, 16, 16, "i16x8" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I32X4, Basic_Flag_SIMD, 16, 16, "i32x4" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_I64X2, Basic_Flag_SIMD, 16, 16, "i64x2" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_F32X4, Basic_Flag_SIMD, 16, 16, "f32x4" } },
+ { Type_Kind_Basic, 0, { Basic_Kind_F64X2, Basic_Flag_SIMD, 16, 16, "f64x2" } },
};
b32 types_are_surface_compatible(Type* t1, Type* t2) {
#define WASM_TYPE_INT64 0x7E
#define WASM_TYPE_FLOAT32 0x7D
#define WASM_TYPE_FLOAT64 0x7C
+#define WASM_TYPE_VAR128 0x7B
#define WASM_TYPE_VOID 0x00
#else
#define WASM_TYPE_INT32 'A'
if (basic->size <= 4) return WASM_TYPE_FLOAT32;
if (basic->size == 8) return WASM_TYPE_FLOAT64;
}
+ if (basic->flags & Basic_Flag_SIMD) return WASM_TYPE_VAR128;
if (basic->size == 0) return WASM_TYPE_VOID;
}
static i32 generate_type_idx(OnyxWasmModule* mod, Type* ft);
static i32 get_element_idx(OnyxWasmModule* mod, AstFunction* func);
-#define LOCAL_I32 0x000000000
-#define LOCAL_I64 0x100000000
-#define LOCAL_F32 0x300000000
-#define LOCAL_F64 0x700000000
+#define LOCAL_I32 0x000000000
+#define LOCAL_I64 0x100000000
+#define LOCAL_F32 0x300000000
+#define LOCAL_F64 0x700000000
+#define LOCAL_V128 0xf00000000
static b32 local_is_wasm_local(AstLocal* local) {
if (local->flags & Ast_Flag_Address_Taken) return 0;
if (wt == WASM_TYPE_INT64) idx = 1;
if (wt == WASM_TYPE_FLOAT32) idx = 2;
if (wt == WASM_TYPE_FLOAT64) idx = 3;
+ if (wt == WASM_TYPE_VAR128) idx = 4;
u64 flag_bits = LOCAL_IS_WASM;
if (wt == WASM_TYPE_INT32) flag_bits |= LOCAL_I32;
if (wt == WASM_TYPE_INT64) flag_bits |= LOCAL_I64;
if (wt == WASM_TYPE_FLOAT32) flag_bits |= LOCAL_F32;
if (wt == WASM_TYPE_FLOAT64) flag_bits |= LOCAL_F64;
+ if (wt == WASM_TYPE_VAR128) flag_bits |= LOCAL_V128;
if (la->freed[idx] > 0) {
la->freed[idx]--;
if (wt == WASM_TYPE_INT64) idx = 1;
if (wt == WASM_TYPE_FLOAT32) idx = 2;
if (wt == WASM_TYPE_FLOAT64) idx = 3;
+ if (wt == WASM_TYPE_VAR128) idx = 4;
assert(la->allocated[idx] > 0 && la->freed[idx] < la->allocated[idx]);
if (value & 0x100000000) idx += la->allocated[0];
if (value & 0x200000000) idx += la->allocated[1];
if (value & 0x400000000) idx += la->allocated[2];
+ if (value & 0x800000000) idx += la->allocated[3];
return (u64) idx;
}
(i32) (func->locals.allocated[0] != 0) +
(i32) (func->locals.allocated[1] != 0) +
(i32) (func->locals.allocated[2] != 0) +
- (i32) (func->locals.allocated[3] != 0);
+ (i32) (func->locals.allocated[3] != 0) +
+ (i32) (func->locals.allocated[4] != 0);
i32 leb_len;
u8* leb = uint_to_uleb128((u64) total_locals, &leb_len);
bh_buffer_append(buff, leb, leb_len);
bh_buffer_write_byte(buff, WASM_TYPE_FLOAT64);
}
+ if (func->locals.allocated[4] != 0) {
+ leb = uint_to_uleb128((u64) func->locals.allocated[4], &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ bh_buffer_write_byte(buff, WASM_TYPE_VAR128);
+ }
return buff->length - prev_len;
}