Skip to content

Commit

Permalink
support non-constant index get in tuple
Browse files Browse the repository at this point in the history
Signed-off-by: Su Yihan <[email protected]>
  • Loading branch information
yviansu committed Jan 29, 2024
1 parent 5260a64 commit 078cd8b
Show file tree
Hide file tree
Showing 6 changed files with 352 additions and 24 deletions.
1 change: 1 addition & 0 deletions lib/builtin/builtin_name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export namespace BuiltinNames {
export const findPropertyFlagAndIndex = 'find_property_flag_and_index';
export const findPropertyType = 'find_property_type';
export const getInfcProperty = 'get_infc_property';
export const getTupleField = 'get_tuple_field';

// builtin globals
export const builtinTypeManglePrefix = 'lib/builtin/lib.type.d';
Expand Down
2 changes: 2 additions & 0 deletions src/backend/binaryen/glue/packType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import {
arrayBufferType,
dataViewType,
numberArrayStructType,
i32ArrayType,
} from './transform.js';
import { typeInfo } from './utils.js';

export const i8ArrayTypeInfo: typeInfo = i8ArrayType;
export const stringTypeInfo: typeInfo = stringType;
export const numberArrayTypeInfo = numberArrayType;
export const i32ArrayTypeInfo = i32ArrayType;
export const stringArrayTypeInfo = stringArrayType;
export const stringArrayStructTypeInfo = stringArrayStructType;
export const stringrefArrayTypeInfo = stringrefArrayType;
Expand Down
15 changes: 15 additions & 0 deletions src/backend/binaryen/glue/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ export function initStructType(
export const i8ArrayType = genarateI8ArrayTypeInfo();
/* array(f64) */
export const numberArrayType = genarateNumberArrayTypeInfo();
/* array(i32) */
export const i32ArrayType = genarateI32ArrayTypeInfo();
/* array(stringref) */
export const stringrefArrayType = genarateStringrefArrayTypeInfo(false);
/* array(i32) */
Expand Down Expand Up @@ -355,6 +357,19 @@ function genarateNumberArrayTypeInfo(): typeInfo {
return numberArrayTypeInfo;
}

// generate i32 array type
function genarateI32ArrayTypeInfo(): typeInfo {
const i32ArrayTypeInfo = initArrayType(
binaryen.i32,
Packed.Not,
true,
true,
-1,
binaryenCAPI._TypeBuilderCreate(1),
);
return i32ArrayTypeInfo;
}

// generate string array type
function genarateStringArrayTypeInfo(struct_wrap: boolean): typeInfo {
const stringTypeInfo = stringType;
Expand Down
256 changes: 256 additions & 0 deletions src/backend/binaryen/lib/init_builtin_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
dataViewTypeInfo,
numberArrayStructTypeInfo,
numberArrayTypeInfo,
i32ArrayTypeInfo,
} from '../glue/packType.js';
import { array_get_data, array_get_length_i32 } from './array_utils.js';
import { SemanticsKind } from '../../../semantics/semantics_nodes.js';
Expand Down Expand Up @@ -4982,6 +4983,250 @@ function string_fromCharCode(module: binaryen.Module) {
return module.block(null, stmts);
}

function WASMStruct_get_field(module: binaryen.Module) {
/* params */
const typeIdArray_idx = 0;
const idxI32Ref_idx = 1;
const ownerRef_idx = 2;
/* vars */
const arrLen_i32_idx = 3;
const loopIdx_i32_idx = 4;
const typeIdRef_idx = 5;
const anyTypedRes_Idx = 6;

const stmts: binaryen.ExpressionRef[] = [];
stmts.push(module.local.set(loopIdx_i32_idx, module.i32.const(0)));
const typeIdArrayValue = module.local.get(
typeIdArray_idx,
i32ArrayTypeInfo.typeRef,
);
const loopIndexValue = module.local.get(loopIdx_i32_idx, binaryen.i32);
const idxI32RefValue = module.local.get(idxI32Ref_idx, binaryen.i32);
const typeIdRefValue = module.local.get(typeIdRef_idx, binaryen.i32);
const ownerRefValue = module.local.get(ownerRef_idx, binaryen.anyref);

const arrLen = binaryenCAPI._BinaryenArrayLen(module.ptr, typeIdArrayValue);
stmts.push(module.local.set(arrLen_i32_idx, arrLen));
/* get the field typeId through for loop */
const loopLabel = 'for_label';
const loopCond = module.i32.lt_s(
loopIndexValue,
module.local.get(arrLen_i32_idx, binaryen.i32),
);
const loopIncrementor = module.local.set(
loopIdx_i32_idx,
module.i32.add(loopIndexValue, module.i32.const(1)),
);
const loopBody: binaryen.ExpressionRef[] = [];
loopBody.push(
module.if(
module.i32.eq(loopIndexValue, idxI32RefValue),
module.block(null, [
module.local.set(
typeIdRef_idx,
binaryenCAPI._BinaryenArrayGet(
module.ptr,
typeIdArrayValue,
idxI32RefValue,
i32ArrayTypeInfo.typeRef,
false,
),
),
]),
),
);
const flattenLoop: FlattenLoop = {
label: loopLabel,
condition: loopCond,
statements: module.block(null, loopBody),
incrementor: loopIncrementor,
};
stmts.push(
module.loop(
loopLabel,
FunctionalFuncs.flattenLoopStatement(
module,
flattenLoop,
SemanticsKind.FOR,
),
),
);
const branches: binaryen.ExpressionRef[] = new Array(7);
branches[0] = module.br(
'case_field_type_is_number',
FunctionalFuncs.isPropTypeIdEqual(
module,
typeIdRefValue,
module.i32.const(PredefinedTypeId.NUMBER),
),
);
branches[1] = module.br(
'case_field_type_is_i32',
FunctionalFuncs.isPropTypeIdEqual(
module,
typeIdRefValue,
module.i32.const(PredefinedTypeId.INT),
),
);
branches[2] = module.br(
'case_field_type_is_i64',
FunctionalFuncs.isPropTypeIdEqual(
module,
typeIdRefValue,
module.i32.const(PredefinedTypeId.WASM_I64),
),
);
branches[3] = module.br(
'case_field_type_is_f32',
FunctionalFuncs.isPropTypeIdEqual(
module,
typeIdRefValue,
module.i32.const(PredefinedTypeId.WASM_F32),
),
);
branches[4] = module.br(
'case_field_type_is_boolean',
FunctionalFuncs.isPropTypeIdEqual(
module,
typeIdRefValue,
module.i32.const(PredefinedTypeId.BOOLEAN),
),
);
branches[5] = module.br(
'case_field_type_is_string',
FunctionalFuncs.isPropTypeIdEqual(
module,
typeIdRefValue,
module.i32.const(PredefinedTypeId.STRING),
),
);
branches[6] = module.br('field_type_default');

let switchBlock = module.block('case_field_type_is_number', branches);
switchBlock = module.block(
'case_field_type_is_i32',
[switchBlock].concat(
module.local.set(
anyTypedRes_Idx,
FunctionalFuncs.generateDynNumber(
module,
module.call(
structdyn.StructDyn.struct_get_indirect_f64,
[ownerRefValue, idxI32RefValue],
binaryen.f64,
),
),
),
module.br('field_type_break'),
),
);
switchBlock = module.block(
'case_field_type_is_i64',
[switchBlock].concat(
module.local.set(
anyTypedRes_Idx,
FunctionalFuncs.generateDynNumber(
module,
module.call(
structdyn.StructDyn.struct_get_indirect_i32,
[ownerRefValue, idxI32RefValue],
binaryen.i32,
),
),
),
module.br('field_type_break'),
),
);
switchBlock = module.block(
'case_field_type_is_f32',
[switchBlock].concat(
module.local.set(
anyTypedRes_Idx,
FunctionalFuncs.generateDynNumber(
module,
module.call(
structdyn.StructDyn.struct_get_indirect_i64,
[ownerRefValue, idxI32RefValue],
binaryen.i64,
),
),
),
module.br('field_type_break'),
),
);
switchBlock = module.block(
'case_field_type_is_boolean',
[switchBlock].concat(
module.local.set(
anyTypedRes_Idx,
FunctionalFuncs.generateDynNumber(
module,
module.call(
structdyn.StructDyn.struct_get_indirect_f32,
[ownerRefValue, idxI32RefValue],
binaryen.f32,
),
),
),
module.br('field_type_break'),
),
);
switchBlock = module.block(
'case_field_type_is_string',
[switchBlock].concat(
module.local.set(
anyTypedRes_Idx,
FunctionalFuncs.generateDynBoolean(
module,
module.call(
structdyn.StructDyn.struct_get_indirect_i32,
[ownerRefValue, idxI32RefValue],
binaryen.i32,
),
),
),
module.br('field_type_break'),
),
);
switchBlock = module.block(
'field_type_default',
[switchBlock].concat(
module.local.set(
anyTypedRes_Idx,
FunctionalFuncs.generateDynString(
module,
module.call(
structdyn.StructDyn.struct_get_indirect_anyref,
[ownerRefValue, idxI32RefValue],
binaryen.anyref,
),
),
),
module.br('field_type_break'),
),
);
switchBlock = module.block(
'field_type_break',
[switchBlock].concat(
module.local.set(
anyTypedRes_Idx,
module.call(
structdyn.StructDyn.struct_get_indirect_anyref,
[ownerRefValue, idxI32RefValue],
binaryen.anyref,
),
),
module.br('field_type_break'),
),
);
stmts.push(switchBlock);
stmts.push(
module.return(module.local.get(anyTypedRes_Idx, binaryen.anyref)),
);

return module.block(null, stmts);
}

export function callBuiltInAPIs(module: binaryen.Module) {
/** Math.sqrt */
module.addFunction(
Expand Down Expand Up @@ -6214,6 +6459,17 @@ export function callBuiltInAPIs(module: binaryen.Module) {
[binaryen.i32, binaryen.i32],
string_fromCharCode(module),
);
module.addFunction(
BuiltinNames.getTupleField,
binaryen.createType([
i32ArrayTypeInfo.typeRef,
binaryen.i32,
binaryen.anyref,
]),
binaryen.anyref,
[binaryen.i32, binaryen.i32, binaryen.i32, binaryen.anyref],
WASMStruct_get_field(module),
);
}

function addArrayMethod(
Expand Down
2 changes: 1 addition & 1 deletion src/backend/binaryen/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ export namespace FunctionalFuncs {
) {
return module.call(
dyntype.dyntype_new_number,
[getDynContextRef(module), dynValue],
[getDynContextRef(module), convertTypeToF64(module, dynValue)],
dyntype.dyn_value_t,
);
}
Expand Down
Loading

0 comments on commit 078cd8b

Please sign in to comment.