mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-20 02:11:31 +00:00
static array stuff
This commit is contained in:
@ -4153,17 +4153,17 @@ function compileTypedArrayGet(
|
||||
WrapMode.NONE
|
||||
));
|
||||
if (getExpressionId(dynamicOffset) == ExpressionId.Const) {
|
||||
constantOffset = getConstValueI32(dynamicOffset);
|
||||
constantOffset = getConstValueI32(dynamicOffset) * type.byteSize;
|
||||
dynamicOffset = 0;
|
||||
} else if (getExpressionId(dynamicOffset) == ExpressionId.Binary) {
|
||||
if (getBinaryOp(dynamicOffset) == BinaryOp.AddI32) {
|
||||
let left = getBinaryLeft(dynamicOffset);
|
||||
let right = getBinaryRight(dynamicOffset);
|
||||
if (getExpressionId(left) == ExpressionId.Const) {
|
||||
constantOffset = getConstValueI32(left);
|
||||
constantOffset = getConstValueI32(left) * type.byteSize;
|
||||
dynamicOffset = right;
|
||||
} else if (getExpressionId(right) == ExpressionId.Const) {
|
||||
constantOffset = getConstValueI32(right);
|
||||
constantOffset = getConstValueI32(right) * type.byteSize;
|
||||
dynamicOffset = left;
|
||||
}
|
||||
}
|
||||
|
@ -183,10 +183,9 @@ export namespace LibrarySymbols {
|
||||
export const ALLOCATE = "ALLOCATE";
|
||||
export const REALLOCATE = "REALLOCATE";
|
||||
export const DISCARD = "DISCARD";
|
||||
// gc
|
||||
export const gc = "gc";
|
||||
export const register = "register";
|
||||
export const link = "link";
|
||||
export const REGISTER = "REGISTER";
|
||||
export const LINK = "LINK";
|
||||
export const WRAPARRAY = "WRAPARRAY";
|
||||
// other
|
||||
export const length = "length";
|
||||
export const byteLength = "byteLength";
|
||||
|
103
src/compiler.ts
103
src/compiler.ts
@ -6693,27 +6693,43 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
var arrayPrototype = assert(this.program.arrayPrototype);
|
||||
var arrayInstance = assert(this.resolver.resolveClass(
|
||||
<ClassPrototype>arrayPrototype,
|
||||
[ elementType ],
|
||||
makeMap()
|
||||
));
|
||||
var arrayInstance = assert(this.resolver.resolveClass(arrayPrototype, [ elementType ]));
|
||||
var arrayType = arrayInstance.type;
|
||||
|
||||
// make a static buffer if possible
|
||||
// if the array is static, make a static arraybuffer segment and wrap it with an array
|
||||
if (isStatic) {
|
||||
// let bufferPtr = this.ensureStaticArrayBuffer(elementType, constantValues);
|
||||
// TODO: runtime.alloc the array header and make it use a copy of the static buffer
|
||||
let arrayBufferInstance = assert(this.program.arrayBufferInstance);
|
||||
let wrapArrayPrototype = assert(this.program.wrapArrayPrototype);
|
||||
let wrapArrayInstance = this.resolver.resolveFunction(wrapArrayPrototype, [ elementType ]);
|
||||
if (!wrapArrayInstance) {
|
||||
this.currentType = arrayType;
|
||||
return module.createUnreachable();
|
||||
}
|
||||
let previousFlow = this.currentFlow;
|
||||
let tempLocal = previousFlow.getTempLocal(arrayBufferInstance.type, false);
|
||||
let flow = Flow.createInline(previousFlow.parentFunction, wrapArrayInstance);
|
||||
flow.addScopedAlias("buffer", arrayBufferInstance.type, tempLocal.index);
|
||||
this.currentFlow = flow;
|
||||
let body = this.compileFunctionBody(wrapArrayInstance);
|
||||
body.unshift(
|
||||
module.createSetLocal(tempLocal.index,
|
||||
this.ensureStaticArrayBuffer(elementType, constantValues)
|
||||
)
|
||||
);
|
||||
previousFlow.freeTempLocal(tempLocal);
|
||||
this.currentFlow = previousFlow;
|
||||
this.currentType = arrayType;
|
||||
return module.createBlock(flow.inlineReturnLabel, body, this.options.nativeSizeType);
|
||||
}
|
||||
|
||||
// and compile an explicit instantiation
|
||||
this.currentType = arrayType;
|
||||
// otherwise compile an explicit instantiation with indexed sets
|
||||
var setter = arrayInstance.lookupOverload(OperatorKind.INDEXED_SET, true);
|
||||
if (!setter) {
|
||||
this.error(
|
||||
DiagnosticCode.Index_signature_in_type_0_only_permits_reading,
|
||||
reportNode.range, arrayInstance.internalName
|
||||
);
|
||||
this.currentType = arrayType;
|
||||
return module.createUnreachable();
|
||||
}
|
||||
var nativeArrayType = arrayType.toNativeType();
|
||||
@ -7945,41 +7961,46 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var module = this.module;
|
||||
var options = this.options;
|
||||
var nativeSizeType = options.nativeSizeType;
|
||||
var classType = classInstance.type;
|
||||
|
||||
// ALLOCATE(payloadSize)
|
||||
// ALLOCATE(payloadSize: usize) -> usize
|
||||
var allocateInstance = assert(program.allocateInstance);
|
||||
if (!this.compileFunction(allocateInstance)) return module.createUnreachable();
|
||||
var alloc = module.createCall(
|
||||
allocateInstance.internalName, [
|
||||
options.isWasm64
|
||||
? module.createI64(classInstance.currentMemoryOffset)
|
||||
: module.createI32(classInstance.currentMemoryOffset)
|
||||
// module.createI32(
|
||||
// ensureGCHook(this, classInstance)
|
||||
// )
|
||||
],
|
||||
nativeSizeType
|
||||
);
|
||||
|
||||
// REGISTER<T>(ref, classId)
|
||||
if (program.gcImplemented) {
|
||||
let registerInstance = assert(program.gcRegisterInstance);
|
||||
if (!this.compileFunction(registerInstance)) return module.createUnreachable();
|
||||
let tempLocal = this.currentFlow.getAndFreeTempLocal(classInstance.type, false);
|
||||
alloc = module.createBlock(null, [
|
||||
module.createCall(
|
||||
registerInstance.internalName, [
|
||||
module.createTeeLocal(tempLocal.index, alloc),
|
||||
module.createI32(classInstance.id)
|
||||
],
|
||||
NativeType.None
|
||||
),
|
||||
module.createGetLocal(tempLocal.index, nativeSizeType)
|
||||
], nativeSizeType);
|
||||
if (!this.compileFunction(allocateInstance)) {
|
||||
this.currentType = classInstance.type;
|
||||
return module.createUnreachable();
|
||||
}
|
||||
|
||||
this.currentType = classInstance.type;
|
||||
return alloc;
|
||||
// REGISTER<T>(ref: usize) -> usize
|
||||
var registerPrototype = assert(program.registerPrototype);
|
||||
var registerInstance = this.resolver.resolveFunction(registerPrototype, [ classType ]);
|
||||
if (!registerInstance) {
|
||||
this.currentType = classType;
|
||||
return module.createUnreachable();
|
||||
}
|
||||
|
||||
// REGISTER<T>(ALLOCATE(sizeof<T>()))
|
||||
var previousFlow = this.currentFlow;
|
||||
var tempLocal = previousFlow.getTempLocal(classType, false);
|
||||
var flow = Flow.createInline(previousFlow.parentFunction, registerInstance);
|
||||
flow.addScopedAlias("ref", this.options.usizeType, tempLocal.index);
|
||||
this.currentFlow = flow;
|
||||
var body = this.compileFunctionBody(registerInstance);
|
||||
body.unshift(
|
||||
module.createSetLocal(tempLocal.index,
|
||||
module.createCall(
|
||||
allocateInstance.internalName, [
|
||||
options.isWasm64
|
||||
? module.createI64(classInstance.currentMemoryOffset)
|
||||
: module.createI32(classInstance.currentMemoryOffset)
|
||||
],
|
||||
nativeSizeType
|
||||
)
|
||||
)
|
||||
);
|
||||
previousFlow.freeTempLocal(tempLocal);
|
||||
this.currentFlow = previousFlow;
|
||||
this.currentType = classType;
|
||||
return module.createBlock(flow.inlineReturnLabel, body, nativeSizeType);
|
||||
}
|
||||
|
||||
/** Makes the initializers for a class's fields. */
|
||||
|
@ -179,7 +179,7 @@ export class Flow {
|
||||
return flow;
|
||||
}
|
||||
|
||||
/** Creates an inline flow within `currentFunction`. */
|
||||
/** Creates an inline flow within `parentFunction`. */
|
||||
static createInline(parentFunction: Function, inlineFunction: Function): Flow {
|
||||
var flow = Flow.create(parentFunction);
|
||||
flow.set(FlowFlags.INLINE_CONTEXT);
|
||||
|
@ -349,6 +349,12 @@ export class Program extends DiagnosticEmitter {
|
||||
reallocateInstance: Function | null = null;
|
||||
/** Runtime discard function. */
|
||||
discardInstance: Function | null = null;
|
||||
/** Runtime register function. */
|
||||
registerPrototype: FunctionPrototype | null = null;
|
||||
/** Runtime link function. */
|
||||
linkPrototype: FunctionPrototype | null = null;
|
||||
/** Runtime wrap array function. */
|
||||
wrapArrayPrototype: FunctionPrototype | null = null;
|
||||
|
||||
/** Next class id. */
|
||||
nextClassId: u32 = 1;
|
||||
@ -357,18 +363,10 @@ export class Program extends DiagnosticEmitter {
|
||||
|
||||
/** Whether a garbage collector is present or not. */
|
||||
get gcImplemented(): bool {
|
||||
return this.gcRegisterInstance !== null;
|
||||
return this.lookupGlobal("__gc_register") !== null;
|
||||
}
|
||||
/** Garbage collector register function called when an object becomes managed. */
|
||||
gcRegisterInstance: Function | null = null;
|
||||
/** Garbage collector link function called when a managed object is referenced from a parent. */
|
||||
gcLinkInstance: Function | null = null;
|
||||
/** Garbage collector mark function called to on reachable managed objects. */
|
||||
gcMarkInstance: Function | null = null;
|
||||
/** Size of a managed object header. */
|
||||
gcHeaderSize: u32 = 0;
|
||||
/** Offset of the GC hook. */
|
||||
gcHookOffset: u32 = 0;
|
||||
gcMarkInstance: Function | null = null; // FIXME
|
||||
|
||||
/** Constructs a new program, optionally inheriting parser diagnostics. */
|
||||
constructor(
|
||||
@ -805,6 +803,18 @@ export class Program extends DiagnosticEmitter {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.discardInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.REGISTER)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.registerPrototype = <FunctionPrototype>element;
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.LINK)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.linkPrototype = <FunctionPrototype>element;
|
||||
}
|
||||
if (element = this.lookupGlobal(LibrarySymbols.WRAPARRAY)) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.wrapArrayPrototype = <FunctionPrototype>element;
|
||||
}
|
||||
}
|
||||
|
||||
// mark module exports, i.e. to apply proper wrapping behavior on the boundaries
|
||||
|
Reference in New Issue
Block a user