mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-16 00:11:28 +00:00
Experimenting with inline-assembler-ish explicit builtins
Starting with explicit loads and stores as part of the respective type namespaces. Might become handy for use with portable code, because these can be polyfilled, while load<T> and store<T> can't.
This commit is contained in:
@ -87,6 +87,14 @@ export function compileCall(
|
||||
? module.createI32(1)
|
||||
: module.createI32(0);
|
||||
}
|
||||
case "isSigned": { // isSigned<T!>() / isSigned<T?>(value: T) -> bool
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.bool;
|
||||
if (!type) return module.createUnreachable();
|
||||
return type.is(TypeFlags.SIGNED)
|
||||
? module.createI32(1)
|
||||
: module.createI32(0);
|
||||
}
|
||||
case "isReference": { // isReference<T!>() / isReference<T?>(value: T) -> bool
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.bool;
|
||||
@ -1668,6 +1676,29 @@ export function compileCall(
|
||||
}
|
||||
}
|
||||
}
|
||||
case "i32.load8_s": return compileLoadInstruction(compiler, Type.i8, operands, Type.i32, reportNode);
|
||||
case "i32.load8_u": return compileLoadInstruction(compiler, Type.u8, operands, Type.u32, reportNode);
|
||||
case "i32.load16_s": return compileLoadInstruction(compiler, Type.i16, operands, Type.i32, reportNode);
|
||||
case "i32.load16_u": return compileLoadInstruction(compiler, Type.u16, operands, Type.u32, reportNode);
|
||||
case "i32.load": return compileLoadInstruction(compiler, Type.i32, operands, Type.i32, reportNode);
|
||||
case "i64.load8_s": return compileLoadInstruction(compiler, Type.i8, operands, Type.i64, reportNode);
|
||||
case "i64.load8_u": return compileLoadInstruction(compiler, Type.u8, operands, Type.u64, reportNode);
|
||||
case "i64.load16_s": return compileLoadInstruction(compiler, Type.i16, operands, Type.i64, reportNode);
|
||||
case "i64.load16_u": return compileLoadInstruction(compiler, Type.u16, operands, Type.u64, reportNode);
|
||||
case "i64.load32_s": return compileLoadInstruction(compiler, Type.i32, operands, Type.i64, reportNode);
|
||||
case "i64.load32_u": return compileLoadInstruction(compiler, Type.u32, operands, Type.u64, reportNode);
|
||||
case "i64.load": return compileLoadInstruction(compiler, Type.i64, operands, Type.i64, reportNode);
|
||||
case "f32.load": return compileLoadInstruction(compiler, Type.f32, operands, Type.f32, reportNode);
|
||||
case "f64.load": return compileLoadInstruction(compiler, Type.f64, operands, Type.f64, reportNode);
|
||||
case "i32.store8": return compileStoreInstruction(compiler, Type.i8, operands, Type.i32, reportNode);
|
||||
case "i32.store16": return compileStoreInstruction(compiler, Type.i16, operands, Type.i32, reportNode);
|
||||
case "i32.store": return compileStoreInstruction(compiler, Type.i32, operands, Type.i32, reportNode);
|
||||
case "i64.store8": return compileStoreInstruction(compiler, Type.i8, operands, Type.i64, reportNode);
|
||||
case "i64.store16": return compileStoreInstruction(compiler, Type.i16, operands, Type.i64, reportNode);
|
||||
case "i64.store32": return compileStoreInstruction(compiler, Type.i32, operands, Type.i64, reportNode);
|
||||
case "i64.store": return compileStoreInstruction(compiler, Type.i64, operands, Type.i64, reportNode);
|
||||
case "f32.store": return compileStoreInstruction(compiler, Type.f32, operands, Type.f32, reportNode);
|
||||
case "f64.store": return compileStoreInstruction(compiler, Type.f64, operands, Type.f64, reportNode);
|
||||
|
||||
// control flow
|
||||
|
||||
@ -2487,3 +2518,29 @@ export function compileAbort(
|
||||
module.createUnreachable()
|
||||
]);
|
||||
}
|
||||
|
||||
/** Explicitly compiles a specific load instruction. */
|
||||
export function compileLoadInstruction(
|
||||
compiler: Compiler,
|
||||
loadType: Type,
|
||||
loadOperands: Expression[],
|
||||
valueType: Type,
|
||||
reportNode: Node
|
||||
): ExpressionRef { // transform to a `<valueType>load<loadType>(offset)` call
|
||||
var loadPrototype = assert(compiler.program.elementsLookup.get("load"));
|
||||
assert(loadPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
return compileCall(compiler, <FunctionPrototype>loadPrototype, [ loadType ], loadOperands, valueType, reportNode);
|
||||
}
|
||||
|
||||
/** Explicitly compiles a specific store instruction. */
|
||||
export function compileStoreInstruction(
|
||||
compiler: Compiler,
|
||||
storeType: Type,
|
||||
storeOperands: Expression[],
|
||||
valueType: Type,
|
||||
reportNode: Node
|
||||
): ExpressionRef { // transform to a `store<storeType>(offset, <valueType>value)` call
|
||||
var storePrototype = assert(compiler.program.elementsLookup.get("store"));
|
||||
assert(storePrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
return compileCall(compiler, <FunctionPrototype>storePrototype, [ storeType ], storeOperands, valueType, reportNode);
|
||||
}
|
||||
|
@ -478,6 +478,7 @@ export class Program extends DiagnosticEmitter {
|
||||
var parentNode = declaration.parent;
|
||||
if (
|
||||
(element.hasDecorator(DecoratorFlags.GLOBAL)) ||
|
||||
(declaration.range.source.is(CommonFlags.BUILTIN)) ||
|
||||
(
|
||||
declaration.range.source.isLibrary &&
|
||||
element.is(CommonFlags.EXPORT) &&
|
||||
@ -489,17 +490,15 @@ export class Program extends DiagnosticEmitter {
|
||||
)
|
||||
)
|
||||
) {
|
||||
let simpleName = declaration.name.text;
|
||||
if (this.elementsLookup.has(simpleName)) {
|
||||
let globalName = declaration.programLevelInternalName;
|
||||
if (this.elementsLookup.has(globalName)) {
|
||||
this.error(
|
||||
DiagnosticCode.Duplicate_identifier_0,
|
||||
declaration.name.range, element.internalName
|
||||
);
|
||||
} else {
|
||||
this.elementsLookup.set(simpleName, element);
|
||||
if (element.is(CommonFlags.BUILTIN)) {
|
||||
element.internalName = simpleName;
|
||||
}
|
||||
this.elementsLookup.set(globalName, element);
|
||||
if (element.is(CommonFlags.BUILTIN)) element.internalName = globalName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1281,11 +1280,12 @@ export class Program extends DiagnosticEmitter {
|
||||
queuedExports, queuedImports
|
||||
);
|
||||
}
|
||||
} else if (statement.namespaceName) {
|
||||
} else if (statement.namespaceName) { // import * as simpleName from "file"
|
||||
let simpleName = statement.namespaceName.text;
|
||||
let internalName = (
|
||||
statement.range.source.internalPath +
|
||||
PATH_DELIMITER +
|
||||
statement.namespaceName.text
|
||||
simpleName
|
||||
);
|
||||
if (this.elementsLookup.has(internalName)) {
|
||||
this.error(
|
||||
@ -1327,7 +1327,7 @@ export class Program extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
// otherwise queue it
|
||||
var indexPart = PATH_DELIMITER + "index";
|
||||
const indexPart = PATH_DELIMITER + "index";
|
||||
var queuedImport = new QueuedImport();
|
||||
queuedImport.internalName = internalName;
|
||||
if (internalPath.endsWith(indexPart)) {
|
||||
|
Reference in New Issue
Block a user