mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-18 17:31:29 +00:00
Load/store constant offset utility
This commit is contained in:
@ -29,7 +29,8 @@ import {
|
||||
HostOp,
|
||||
NativeType,
|
||||
ExpressionRef,
|
||||
FunctionTypeRef
|
||||
FunctionTypeRef,
|
||||
ExpressionId
|
||||
} from "./module";
|
||||
|
||||
import {
|
||||
@ -211,6 +212,8 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
var type: Type,
|
||||
ftype: FunctionTypeRef;
|
||||
|
||||
var offset: i32;
|
||||
|
||||
// NOTE that some implementations below make use of the select expression where straight-forward.
|
||||
// whether worth or not should probably be tested once it's known if/how embedders handle it.
|
||||
// search: createSelect
|
||||
@ -1337,11 +1340,14 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
|
||||
// memory access
|
||||
|
||||
case "load": // load<T!>(offset: usize) -> T
|
||||
if (operands.length != 1) {
|
||||
case "load": // load<T!>(offset: usize, constantOffset?: usize) -> T
|
||||
if (operands.length < 1 || operands.length > 2) {
|
||||
if (!(typeArguments && typeArguments.length == 1))
|
||||
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0");
|
||||
compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "1", operands.length.toString(10));
|
||||
if (operands.length < 1)
|
||||
compiler.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, "1", operands.length.toString(10));
|
||||
else
|
||||
compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "2", operands.length.toString(10));
|
||||
return module.createUnreachable();
|
||||
}
|
||||
if (!(typeArguments && typeArguments.length == 1)) {
|
||||
@ -1351,15 +1357,21 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
return module.createUnreachable();
|
||||
}
|
||||
arg0 = compiler.compileExpression(operands[0], usizeType);
|
||||
offset = operands.length == 2 ? evaluateConstantOffset(compiler, operands[1]) : 0; // reports
|
||||
if (offset < 0)
|
||||
return module.createUnreachable();
|
||||
compiler.currentType = typeArguments[0];
|
||||
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0, typeArguments[0].toNativeType());
|
||||
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0, typeArguments[0].toNativeType(), offset);
|
||||
|
||||
case "store": // store<T?>(offset: usize, value: T) -> void
|
||||
case "store": // store<T?>(offset: usize, value: T, constantOffset?: usize) -> void
|
||||
compiler.currentType = Type.void;
|
||||
if (operands.length != 2) {
|
||||
if (operands.length < 2 || operands.length > 3) {
|
||||
if (typeArguments && typeArguments.length != 1)
|
||||
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments.length.toString(10));
|
||||
compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "2", operands.length.toString(10));
|
||||
if (operands.length < 2)
|
||||
compiler.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, "2", operands.length.toString(10));
|
||||
else
|
||||
compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "3", operands.length.toString(10));
|
||||
return module.createUnreachable();
|
||||
}
|
||||
if (typeArguments) {
|
||||
@ -1374,8 +1386,11 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
arg1 = compiler.compileExpression(operands[1], Type.i32, ConversionKind.NONE);
|
||||
}
|
||||
type = compiler.currentType;
|
||||
offset = operands.length == 3 ? evaluateConstantOffset(compiler, operands[2]) : 0; // reports
|
||||
if (offset < 0)
|
||||
return module.createUnreachable();
|
||||
compiler.currentType = Type.void;
|
||||
return module.createStore(type.byteSize, arg0, arg1, type.toNativeType());
|
||||
return module.createStore(type.byteSize, arg0, arg1, type.toNativeType(), offset);
|
||||
|
||||
case "sizeof": // sizeof<T!>() -> usize
|
||||
compiler.currentType = usizeType;
|
||||
@ -1827,6 +1842,34 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
||||
return module.createUnreachable();
|
||||
}
|
||||
|
||||
function evaluateConstantOffset(compiler: Compiler, expression: Expression): i32 {
|
||||
var expr: ExpressionRef;
|
||||
var value: i32;
|
||||
if (compiler.options.target == Target.WASM64) {
|
||||
expr = compiler.precomputeExpression(expression, Type.i64);
|
||||
if (
|
||||
_BinaryenExpressionGetId(expr) != ExpressionId.Const ||
|
||||
_BinaryenExpressionGetType(expr) != NativeType.I64 ||
|
||||
_BinaryenConstGetValueI64High(expr) != 0 ||
|
||||
(value = _BinaryenConstGetValueI64Low(expr)) < 0
|
||||
) {
|
||||
compiler.error(DiagnosticCode.Operation_not_supported, expression.range);
|
||||
value = -1;
|
||||
}
|
||||
} else {
|
||||
expr = compiler.precomputeExpression(expression, Type.i32);
|
||||
if (
|
||||
_BinaryenExpressionGetId(expr) != ExpressionId.Const ||
|
||||
_BinaryenExpressionGetType(expr) != NativeType.I32 ||
|
||||
(value = _BinaryenConstGetValueI32(expr)) < 0
|
||||
) {
|
||||
compiler.error(DiagnosticCode.Operation_not_supported, expression.range);
|
||||
value = -1;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Compiles a memory allocation for an instance of the specified class. */
|
||||
export function compileAllocate(compiler: Compiler, cls: Class, reportNode: Node): ExpressionRef {
|
||||
var program = cls.program;
|
||||
|
Reference in New Issue
Block a user