diff --git a/src/backend/binaryen/wasm_expr_gen.ts b/src/backend/binaryen/wasm_expr_gen.ts index f773b6d..73cf329 100644 --- a/src/backend/binaryen/wasm_expr_gen.ts +++ b/src/backend/binaryen/wasm_expr_gen.ts @@ -92,6 +92,7 @@ import { ValueType, ValueTypeKind, ValueTypeWithArguments, + WASMArrayType, } from '../../semantics/value_types.js'; import { UnimplementError } from '../../error.js'; import { @@ -3731,8 +3732,10 @@ export class WASMExpressionGen { private wasmNewLiteralArray(value: NewLiteralArrayValue) { switch (value.type.kind) { case ValueTypeKind.WASM_ARRAY: { - console.log(value.type.kind); - break; + return this.wasmElemsToArr( + value.initValues, + value.type as WASMArrayType, + ); } case ValueTypeKind.WASM_STRUCT: { console.log(value.type.kind); @@ -4591,14 +4594,22 @@ export class WASMExpressionGen { throw Error('not implemented'); } - private wasmElemsToArr(values: SemanticsValue[], arrType: ArrayType) { + private wasmElemsToArr( + values: SemanticsValue[], + arrType: ArrayType | WASMArrayType, + ) { const arrayLen = values.length; let elemRefs: binaryen.ExpressionRef[] = []; const srcArrRefs: binaryen.ExpressionRef[] = []; const arrayOriHeapType = - this.wasmTypeGen.getWASMArrayOriHeapType(arrType); + arrType instanceof ArrayType + ? this.wasmTypeGen.getWASMArrayOriHeapType(arrType) + : this.wasmTypeGen.getWASMHeapType(arrType); const arrayStructHeapType = this.wasmTypeGen.getWASMHeapType(arrType); - const elemType = arrType.element; + const elemType = + arrType instanceof ArrayType + ? arrType.element + : arrType.arrayType.element; const statementArray: binaryenCAPI.ExpressionRef[] = []; for (let i = 0; i < arrayLen; i++) { let elemValue = values[i]; @@ -4906,26 +4917,30 @@ export class WASMExpressionGen { resConcatArr.local.type, ), ); - const arrayStructRef = binaryenCAPI._BinaryenStructNew( - this.module.ptr, - arrayToPtr([resConcatArr.ref, newArrLenRef]).ptr, - 2, - arrayStructHeapType, - ); - const newArrStructLocal = - this.wasmCompiler.currentFuncCtx!.insertTmpVar( - binaryen.getExpressionType(arrayStructRef), + if (arrType instanceof ArrayType) { + const arrayStructRef = binaryenCAPI._BinaryenStructNew( + this.module.ptr, + arrayToPtr([resConcatArr.ref, newArrLenRef]).ptr, + 2, + arrayStructHeapType, ); - const setNewArrStructLocal = this.module.local.set( - newArrStructLocal.index, - arrayStructRef, - ); - const getNewArrStructLocal = this.module.local.get( - newArrStructLocal.index, - newArrStructLocal.type, - ); - this.wasmCompiler.currentFuncCtx!.insert(setNewArrStructLocal); - return getNewArrStructLocal; + const newArrStructLocal = + this.wasmCompiler.currentFuncCtx!.insertTmpVar( + binaryen.getExpressionType(arrayStructRef), + ); + const setNewArrStructLocal = this.module.local.set( + newArrStructLocal.index, + arrayStructRef, + ); + const getNewArrStructLocal = this.module.local.get( + newArrStructLocal.index, + newArrStructLocal.type, + ); + this.wasmCompiler.currentFuncCtx!.insert(setNewArrStructLocal); + return getNewArrStructLocal; + } else { + return resConcatArr.ref; + } } private wasmArrayConcat( diff --git a/src/backend/binaryen/wasm_type_gen.ts b/src/backend/binaryen/wasm_type_gen.ts index bbb08d2..bb1989d 100644 --- a/src/backend/binaryen/wasm_type_gen.ts +++ b/src/backend/binaryen/wasm_type_gen.ts @@ -54,6 +54,12 @@ import { BuiltinNames } from '../../../lib/builtin/builtin_name.js'; import { VarValue } from '../../semantics/value.js'; import { needSpecialized } from '../../semantics/type_creator.js'; import { getConfig } from '../../../config/config_mgr.js'; +import { + MutabilityKind, + NullabilityKind, + PackedTypeKind, +} from '../../utils.js'; +import { typeInfo } from './glue/utils.js'; export class WASMTypeGen { private typeMap: Map = new Map(); @@ -511,7 +517,7 @@ export class WASMTypeGen { this.typeMap.set(type, this.getWASMValueType(type.memberType)); } - createWASMTupleType(type: TupleType, baseType?: binaryenCAPI.HeapTypeRef) { + createWASMTupleType(type: TupleType) { const fieldTypesListRef = new Array(); for (const elementType of type.elements) { fieldTypesListRef.push(this.getWASMValueType(elementType)); @@ -533,7 +539,6 @@ export class WASMTypeGen { true, buildIndex, tb, - baseType, ); this.typeMap.set(type, tupleTypeInfo.typeRef); @@ -560,24 +565,137 @@ export class WASMTypeGen { } createWASMArrayRawType(type: WASMArrayType) { - this.createWASMArrayType(type.arrayType); - const existedArrType = this.oriArrayTypeMap.get(type.arrayType)!; - const existedArrHeapType = this.oriArrayHeapTypeMap.get( - type.arrayType, - )!; - this.typeMap.set(type, existedArrType); - this.heapTypeMap.set(type, existedArrHeapType); + let arrRawTypeRef: binaryen.Type; + let arrRawHeapTypeRef: binaryenCAPI.HeapTypeRef; + let arrayRawTypeInfo: typeInfo; + if ( + type.packedTypeKind === PackedTypeKind.Not_Packed && + type.mutability === MutabilityKind.Mutable && + type.nullability === NullabilityKind.Nullable + ) { + arrRawTypeRef = this.getWASMArrayOriType(type.arrayType); + arrRawHeapTypeRef = this.getWASMArrayOriHeapType(type.arrayType); + arrayRawTypeInfo = { + typeRef: arrRawTypeRef, + heapTypeRef: arrRawHeapTypeRef, + }; + } else { + const elemTypeRef = this.getWASMValueType(type.arrayType.element); + let elementPackedType: binaryenCAPI.PackedType = Packed.Not; + switch (type.packedTypeKind) { + case PackedTypeKind.I8: { + elementPackedType = Packed.I8; + break; + } + case PackedTypeKind.I16: { + elementPackedType = Packed.I16; + break; + } + } + let elementMutable: binaryenCAPI.bool = true; + if (type.mutability === MutabilityKind.Immutable) { + elementMutable = false; + } + let nullable: binaryenCAPI.bool = true; + if (type.nullability === NullabilityKind.NonNullable) { + nullable = false; + } + const tb = binaryenCAPI._TypeBuilderCreate(1); + const buildIndex = this.createTbIndexForType(type.arrayType); + arrayRawTypeInfo = initArrayType( + elemTypeRef, + elementPackedType, + elementMutable, + nullable, + buildIndex, + tb, + ); + } + + this.typeMap.set(type, arrayRawTypeInfo.typeRef); + this.heapTypeMap.set(type, arrayRawTypeInfo.heapTypeRef); } createWASMStructRawType(type: WASMStructType) { - const baseTypeRef = type.baseType - ? this.getWASMType(type.baseType) - : undefined; - this.createWASMTupleType(type.tupleType, baseTypeRef); - const existedStructType = this.typeMap.get(type.tupleType)!; - const existedStructHeapType = this.heapTypeMap.get(type.tupleType)!; - this.typeMap.set(type, existedStructType); - this.heapTypeMap.set(type, existedStructHeapType); + let structRawTypeRef: binaryen.Type; + let structRawHeapTypeRef: binaryenCAPI.HeapTypeRef; + let structRawTypeInfo: typeInfo; + const isEachFieldNotPacked = type.packedTypeKinds.every( + (value) => value === PackedTypeKind.Not_Packed, + ); + const isEachFieldMutable = type.mutabilitys.every( + (value) => value === MutabilityKind.Mutable, + ); + const isNullable = + type.nullability === NullabilityKind.Nullable ? true : false; + if ( + isEachFieldNotPacked && + isEachFieldMutable && + isNullable && + !type.baseType + ) { + structRawTypeRef = this.getWASMType(type.tupleType); + structRawHeapTypeRef = this.getWASMHeapType(type.tupleType); + structRawTypeInfo = { + typeRef: structRawTypeRef, + heapTypeRef: structRawHeapTypeRef, + }; + } else { + const fieldTypesListRef = new Array(); + for (const elementType of type.tupleType.elements) { + fieldTypesListRef.push(this.getWASMValueType(elementType)); + } + const fieldPackedTypesListRef = new Array( + fieldTypesListRef.length, + ); + for (const packedType of type.packedTypeKinds) { + let fieldPackedType = Packed.Not; + switch (packedType) { + case PackedTypeKind.I8: { + fieldPackedType = Packed.I8; + break; + } + case PackedTypeKind.I16: { + fieldPackedType = Packed.I16; + break; + } + } + fieldPackedTypesListRef.push(fieldPackedType); + } + const fieldMutablesListRef = new Array( + fieldTypesListRef.length, + ); + for (const mutability of type.mutabilitys) { + let fieldMutability = true; + if (mutability === MutabilityKind.Immutable) { + fieldMutability = false; + } + fieldMutablesListRef.push(fieldMutability); + } + let nullable = true; + if (type.nullability === NullabilityKind.NonNullable) { + nullable = false; + } + const baseTypeRef = type.baseType + ? this.getWASMType(type.baseType) + : undefined; + + const tb = binaryenCAPI._TypeBuilderCreate(1); + const buildIndex = this.createTbIndexForType(type.tupleType); + structRawTypeInfo = initStructType( + fieldTypesListRef, + fieldPackedTypesListRef, + fieldMutablesListRef, + fieldTypesListRef.length, + nullable, + buildIndex, + tb, + baseTypeRef, + ); + } + + this.typeMap.set(type, structRawTypeInfo.typeRef); + this.heapTypeMap.set(type, structRawTypeInfo.heapTypeRef); } getObjSpecialSuffix(type: ArrayType) {