Skip to content

Commit be66abb

Browse files
committed
Initial static arrays of basic element types; Fixed member names in generic contexts
1 parent 2c0ddf4 commit be66abb

25 files changed

+6444
-283
lines changed

dist/asc.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/asc.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compiler.ts

Lines changed: 98 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ import {
119119
typesToNativeTypes
120120
} from "./types";
121121

122+
import {
123+
writeI32,
124+
writeI64,
125+
writeF32,
126+
writeF64
127+
} from "./util";
128+
122129
/** Compilation target. */
123130
export enum Target {
124131
/** WebAssembly with 32-bit pointers. */
@@ -4564,11 +4571,10 @@ export class Compiler extends DiagnosticEmitter {
45644571
let classType = contextualType.classType;
45654572
if (
45664573
classType &&
4567-
classType == this.program.elementsLookup.get("Array") &&
4568-
classType.typeArguments && classType.typeArguments.length == 1
4574+
classType.prototype == this.program.elementsLookup.get("Array")
45694575
) {
45704576
return this.compileStaticArray(
4571-
classType.typeArguments[0],
4577+
assert(classType.typeArguments)[0],
45724578
(<ArrayLiteralExpression>expression).elementExpressions,
45734579
expression
45744580
);
@@ -4725,29 +4731,38 @@ export class Compiler extends DiagnosticEmitter {
47254731
}
47264732

47274733
compileStaticArray(elementType: Type, expressions: (Expression | null)[], reportNode: Node): ExpressionRef {
4728-
// compile as static if all element expressions are precomputable, otherwise
4729-
// initialize in place.
47304734
var isStatic = true;
4731-
var size = expressions.length;
4732-
47334735
var module = this.module;
4736+
4737+
// obtain the array type
4738+
var arrayPrototype = assert(this.program.elementsLookup.get("Array"));
4739+
if (!arrayPrototype || arrayPrototype.kind != ElementKind.CLASS_PROTOTYPE) return module.createUnreachable();
4740+
var arrayType = (<ClassPrototype>arrayPrototype).resolve([ elementType ]);
4741+
if (!arrayType) return module.createUnreachable();
4742+
4743+
var elementSize = expressions.length;
47344744
var nativeType = elementType.toNativeType();
47354745
var values: usize;
4746+
var memorySize: usize;
47364747
switch (nativeType) {
47374748
case NativeType.I32: {
4738-
values = changetype<usize>(new Int32Array(size));
4749+
values = changetype<usize>(new Int32Array(elementSize));
4750+
memorySize = elementSize * 4;
47394751
break;
47404752
}
47414753
case NativeType.I64: {
4742-
values = changetype<usize>(new Array<I64>(size));
4754+
values = changetype<usize>(new Array<I64>(elementSize));
4755+
memorySize = elementSize * 8;
47434756
break;
47444757
}
47454758
case NativeType.F32: {
4746-
values = changetype<usize>(new Float32Array(size));
4759+
values = changetype<usize>(new Float32Array(elementSize));
4760+
memorySize = elementSize * 4;
47474761
break;
47484762
}
47494763
case NativeType.F64: {
4750-
values = changetype<usize>(new Float64Array(size));
4764+
values = changetype<usize>(new Float64Array(elementSize));
4765+
memorySize = elementSize * 8;
47514766
break;
47524767
}
47534768
default: {
@@ -4760,9 +4775,10 @@ export class Compiler extends DiagnosticEmitter {
47604775
}
47614776
}
47624777

4763-
var exprs = new Array<ExpressionRef>(size);
4778+
// precompute value expressions
4779+
var exprs = new Array<ExpressionRef>(elementSize);
47644780
var expr: BinaryenExpressionRef;
4765-
for (let i = 0; i < size; ++i) {
4781+
for (let i = 0; i < elementSize; ++i) {
47664782
exprs[i] = expressions[i]
47674783
? this.compileExpression(<Expression>expressions[i], elementType)
47684784
: elementType.toNativeZero(module);
@@ -4801,14 +4817,78 @@ export class Compiler extends DiagnosticEmitter {
48014817
}
48024818
}
48034819

4820+
var usizeTypeSize = this.options.usizeType.byteSize;
4821+
var headerSize = usizeTypeSize + 4 + 4; // memory + capacity + length
4822+
48044823
if (isStatic) {
4805-
// TODO: convert to Uint8Array and create the segment
4824+
let buffer = new Uint8Array(headerSize + memorySize);
4825+
let segment = this.addMemorySegment(buffer);
4826+
4827+
// make header
4828+
let offset = 0;
4829+
if (usizeTypeSize == 8) {
4830+
writeI64(i64_add(segment.offset, i64_new(headerSize)), buffer, 0); // memory
4831+
} else {
4832+
assert(i64_high(segment.offset) == 0);
4833+
writeI32(i64_low(segment.offset) + headerSize, buffer, 0); // memory
4834+
}
4835+
offset += usizeTypeSize;
4836+
writeI32(elementSize, buffer, offset); // capacity
4837+
offset += 4;
4838+
writeI32(elementSize, buffer, offset); // length
4839+
offset += 4;
4840+
assert(offset == headerSize);
4841+
4842+
// make memory
4843+
switch (nativeType) {
4844+
case NativeType.I32: {
4845+
for (let i = 0; i < elementSize; ++i) {
4846+
writeI32(changetype<i32[]>(values)[i], buffer, offset); offset += 4;
4847+
}
4848+
break;
4849+
}
4850+
case NativeType.I64: {
4851+
for (let i = 0; i < elementSize; ++i) {
4852+
writeI64(changetype<I64[]>(values)[i], buffer, offset); offset += 8;
4853+
}
4854+
break;
4855+
}
4856+
case NativeType.F32: {
4857+
for (let i = 0; i < elementSize; ++i) {
4858+
writeF32(changetype<f32[]>(values)[i], buffer, offset); offset += 4;
4859+
}
4860+
break;
4861+
}
4862+
case NativeType.F64: {
4863+
for (let i = 0; i < elementSize; ++i) {
4864+
writeF64(changetype<f64[]>(values)[i], buffer, offset); offset += 8;
4865+
}
4866+
break;
4867+
}
4868+
default: {
4869+
assert(false);
4870+
this.error(
4871+
DiagnosticCode.Operation_not_supported,
4872+
reportNode.range
4873+
);
4874+
return module.createUnreachable();
4875+
}
4876+
}
4877+
assert(offset == headerSize + memorySize);
4878+
this.currentType = arrayType.type;
4879+
return usizeTypeSize == 8
4880+
? module.createI64(
4881+
i64_low(segment.offset),
4882+
i64_high(segment.offset)
4883+
)
4884+
: module.createI32(
4885+
i64_low(segment.offset)
4886+
);
48064887
} else {
4807-
// TODO: initialize in place
4888+
// TODO: static elements *could* go into data segments while dynamic ones are initialized
4889+
// on top? any benefits?
4890+
throw new Error("not implemented");
48084891
}
4809-
// TODO: alternatively, static elements could go into data segments while
4810-
// dynamic ones are initialized on top? any benefits? (doesn't seem so)
4811-
throw new Error("not implemented");
48124892
}
48134893

48144894
compileNewExpression(expression: NewExpression, contextualType: Type): ExpressionRef {

src/glue/js/float.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/** @module glue/js *//***/
2+
3+
declare function f32_as_i32(value: f32): i32;
4+
declare function i32_as_f32(value: i32): f32;
5+
declare function f64_as_i64(value: f64): I64;
6+
declare function i64_as_f64(value: I64): f64;

src/glue/js/float.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const F64 = new Float64Array(1);
2+
const F32 = new Float32Array(F64.buffer);
3+
const I32 = new Int32Array(F64.buffer);
4+
5+
global.f32_as_i32 = function(value) {
6+
F32[0] = value;
7+
return I32[0];
8+
};
9+
10+
global.i32_as_f32 = function(value) {
11+
I32[0] = value;
12+
return F32[0];
13+
};
14+
15+
global.f64_as_i64 = function(value) {
16+
F64[0] = value;
17+
return i64_new(I32[0], I32[1]);
18+
};
19+
20+
global.i64_as_f64 = function(value) {
21+
I32[0] = i64_low(value);
22+
I32[1] = i64_high(value);
23+
return F64[0];
24+
};

src/glue/js/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
import "../../../std/portable";
88
import "./binaryen";
99
import "./i64";
10+
import "./float";

src/glue/wasm/float.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@global
2+
function f32_as_i32(value: f32): i32 {
3+
return reinterpret<i32>(value);
4+
}
5+
6+
@global
7+
function i32_as_f32(value: i32): f32 {
8+
return reinterpret<f32>(value);
9+
}
10+
11+
@global
12+
function f64_as_i64(value: f64): i64 {
13+
return reinterpret<i64>(value);
14+
}
15+
16+
@global
17+
function i64_as_f64(value: i64): f64 {
18+
return reinterpret<f64>(value);
19+
}

src/glue/wasm/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
*//***/
66

77
import "./i64";
8+
import "./float";

0 commit comments

Comments
 (0)