More options for asc

This commit is contained in:
dcodeIO 2017-12-04 19:26:50 +01:00
parent 0e6bfa45f8
commit df3e34f2aa
17 changed files with 565 additions and 32 deletions

View File

@ -17,5 +17,13 @@
"validate": {
"desc": "Validate the module.",
"type": "boolean"
},
"outFile": {
"desc": "Specify the output file (binary format).",
"type": "string"
},
"textFile": {
"desc": "Specify the output file (text format).",
"type": "string"
}
}

View File

@ -1,5 +1,3 @@
/// <reference path="../src/glue/binaryen.d.ts" />
import * as fs from "fs";
import * as path from "path";
import * as minimist from "minimist";
@ -112,5 +110,17 @@ if (args["validate"])
if (args["optimize"])
module.optimize();
_BinaryenModulePrint(module.ref);
let hasOutput = false;
if (args["outFile"]) {
fs.writeFileSync(args["outFile"], module.toBinary());
hasOutput = true;
}
if (args["textFile"]) {
fs.writeFileSync(args["textFile"], module.toText(), { encoding: "utf8" });
hasOutput = true;
}
if (!hasOutput)
module.print();
module.dispose();

View File

@ -412,7 +412,9 @@ export class Compiler extends DiagnosticEmitter {
if (!element || element.kind != ElementKind.FUNCTION_PROTOTYPE)
throw new Error("unexpected missing function");
const instance: Function | null = this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, typeArguments, contextualTypeArguments, alternativeReportNode);
if (instance && declaration.range.source.isEntry && declaration.parent == declaration.range.source && hasModifier(ModifierKind.EXPORT, declaration.modifiers))
if (!instance)
return;
if (declaration.range.source.isEntry && declaration.parent == declaration.range.source && hasModifier(ModifierKind.EXPORT, declaration.modifiers))
this.module.addExport(instance.internalName, declaration.identifier.name);
}
@ -431,19 +433,29 @@ export class Compiler extends DiagnosticEmitter {
if (!declaration)
throw new Error("unexpected missing declaration");
if (!declaration.statements) {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.identifier.range);
return false;
if (instance.isDeclare) {
if (declaration.statements) {
this.error(DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts, declaration.identifier.range);
return false;
}
} else {
if (!declaration.statements) {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.identifier.range);
return false;
}
}
instance.isCompiled = true;
// compile statements
const previousFunction: Function = this.currentFunction;
this.currentFunction = instance;
const stmts: ExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
this.currentFunction = previousFunction;
let stmts: ExpressionRef[] | null = null;
if (!instance.isDeclare) {
const previousFunction: Function = this.currentFunction;
this.currentFunction = instance;
stmts = this.compileStatements(<Statement[]>declaration.statements);
this.currentFunction = previousFunction;
}
// create the function
// create the function type
let k: i32 = instance.parameters.length;
const binaryenResultType: NativeType = typeToNativeType(instance.returnType);
const binaryenParamTypes: NativeType[] = new Array(k);
@ -456,8 +468,14 @@ export class Compiler extends DiagnosticEmitter {
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(binaryenResultType, binaryenParamTypes);
if (!typeRef)
typeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes);
// create the function
const internalName: string = instance.internalName;
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, stmts, NativeType.None));
if (instance.isDeclare) {
this.module.addImport(internalName, "env", declaration.identifier.name, typeRef);
} else {
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
}
return true;
}
@ -1732,7 +1750,7 @@ export class Compiler extends DiagnosticEmitter {
this.compileFunction(functionInstance);
// imported function
if (functionInstance.isImport)
if (functionInstance.isDeclare)
return this.module.createCallImport(functionInstance.internalName, operands, typeToNativeType(functionInstance.returnType));
// internal function

View File

@ -12,3 +12,23 @@ const binaryen = require("binaryen");
for (const key in binaryen)
if (/^_(?:Binaryen|Relooper|malloc$|free$)/.test(key))
globalScope[key] = binaryen[key];
import { Module } from "../module";
Module.prototype.toBinary = function(bufferSize = 1048576): Uint8Array {
const ptr = _malloc(bufferSize);
const len = this.write(ptr, bufferSize);
const ret = new Uint8Array(len);
ret.set(binaryen.HEAPU8.subarray(ptr, ptr + len));
_free(ptr);
return ret;
}
Module.prototype.toText = function(): string {
let previousPrint: any = (<any>binaryen)["print"];
let ret: string = "";
binaryen["print"] = function(x: string): void { ret += x + "\n" };
this.print();
binaryen["print"] = previousPrint;
return ret;
}

View File

@ -617,11 +617,21 @@ export class Module {
return _BinaryenModuleInterpret(this.ref);
}
toBinary(): Uint8Array {
write(output: usize, outputSize: usize = 1048576): usize {
return _BinaryenModuleWrite(this.ref, output, outputSize);
}
print(): void {
return _BinaryenModulePrint(this.ref);
}
toBinary(bufferSize: usize = 1048576): Uint8Array {
// FIXME: target specific / JS glue overrides this
throw new Error("not implemented");
}
toText(): string {
// FIXME: target specific / JS glue overrides this
throw new Error("not implemented");
}

View File

@ -380,6 +380,9 @@ export class Program extends DiagnosticEmitter {
else
this.exports.set(internalName, prototype);
}
if (hasModifier(ModifierKind.DECLARE, declaration.modifiers)) {
prototype.isDeclare = true;
}
}
private initializeImports(statement: ImportStatement, queuedExports: Map<string,QueuedExport>, queuedImports: QueuedImport[]): void {
@ -689,6 +692,7 @@ export abstract class Element {
isCompiled: bool = false;
isImport: bool = false;
isBuiltin: bool = false;
isDeclare: bool = false;
constructor(program: Program, internalName: string) {
this.program = program;
@ -922,6 +926,7 @@ export class Function extends Element {
this.returnType = returnType;
this.instanceMethodOf = instanceMethodOf;
this.isBuiltin = prototype.isBuiltin;
this.isDeclare = prototype.isDeclare;
let localIndex: i32 = 0;
if (instanceMethodOf) {
this.locals.set("this", new Local(prototype.program, "this", localIndex++, instanceMethodOf.type));

View File

@ -0,0 +1,13 @@
var binaryen = require("binaryen");
// "unexpected false: module function exports must be found"
var mod = new binaryen.Module();
var funcType = mod.addFunctionType("v", binaryen.none, []);
var func = mod.addImport("test", "env", "test", funcType);
mod.addExport("test", "test");
console.log(mod.emitText());
if (!mod.validate())
console.log("-> does not validate");

View File

@ -11,17 +11,6 @@ import { Module } from "../src/module";
import { Parser } from "../src/parser";
import { diff } from "./util/diff";
// TODO: implement properly in module.ts
import * as binaryen from "binaryen";
Module.prototype.toText = function(): string {
let old: any = (<any>binaryen)["print"];
let ret: string = "";
(<any>binaryen)["print"] = function(x: string): void { ret += x + "\n" };
_BinaryenModulePrint(this.ref);
(<any>binaryen)["print"] = old;
return ret;
}
const isCreate = process.argv[2] === "--create";
const filter = process.argv.length > 2 && !isCreate ? "*" + process.argv[2] + "*.ts" : "*.ts";

View File

@ -177,13 +177,40 @@
)
(set_global $builtins/i
(i32.load
(i32.const 4)
(i32.const 8)
)
)
(i32.store
(i32.const 4)
(i32.const 8)
(get_global $builtins/i)
)
(set_global $builtins/I
(i64.load
(i32.const 8)
)
)
(i64.store
(i32.const 8)
(get_global $builtins/I)
)
(set_global $builtins/f
(f32.load
(i32.const 8)
)
)
(f32.store
(i32.const 8)
(get_global $builtins/f)
)
(set_global $builtins/F
(f64.load
(i32.const 8)
)
)
(f64.store
(i32.const 8)
(get_global $builtins/F)
)
(if
(f32.eq
(tee_local $0

View File

@ -119,8 +119,14 @@ sizeof<isize>();
sizeof<f32>();
sizeof<f64>();
i = load<i32>(4);
store<i32>(4, i);
i = load<i32>(8);
store<i32>(8, i);
I = load<i64>(8);
store<i64>(8, I);
f = load<f32>(8);
store<f32>(8, f);
F = load<f64>(8);
store<f64>(8, F);
if (NaN == NaN)
unreachable();

View File

@ -520,13 +520,40 @@
)
(set_global $builtins/i
(i32.load
(i32.const 4)
(i32.const 8)
)
)
(i32.store
(i32.const 4)
(i32.const 8)
(get_global $builtins/i)
)
(set_global $builtins/I
(i64.load
(i32.const 8)
)
)
(i64.store
(i32.const 8)
(get_global $builtins/I)
)
(set_global $builtins/f
(f32.load
(i32.const 8)
)
)
(f32.store
(i32.const 8)
(get_global $builtins/f)
)
(set_global $builtins/F
(f64.load
(i32.const 8)
)
)
(f64.store
(i32.const 8)
(get_global $builtins/F)
)
(if
(f64.eq
(f64.const nan:0x8000000000000)

View File

@ -0,0 +1,5 @@
(module
(memory $0 1)
(data (i32.const 4) "\08")
(export "memory" (memory $0))
)

View File

@ -0,0 +1,4 @@
declare function external(): void;
// FIXME: "unexpected false: module function exports must be found"
export { external };

View File

@ -0,0 +1,37 @@
(module
(type $v (func))
(import "env" "external" (func $declare/external))
(memory $0 1)
(data (i32.const 4) "\08\00\00\00")
(export "external" (func $declare/external))
(export "memory" (memory $0))
)
(;
[program.elements]
clz
ctz
popcnt
rotl
rotr
abs
ceil
copysign
floor
max
min
nearest
sqrt
trunc
current_memory
grow_memory
unreachable
isNaN
isFinite
assert
sizeof
load
store
declare/external
[program.exports]
declare/external
;)

View File

@ -1,5 +1,9 @@
(module
(type $v (func))
(global $logical/i (mut i32) (i32.const 0))
(global $logical/I (mut i64) (i64.const 0))
(global $logical/f (mut f32) (f32.const 0))
(global $logical/F (mut f64) (f64.const 0))
(memory $0 1)
(data (i32.const 4) "\08")
(export "memory" (memory $0))
@ -7,6 +11,8 @@
(func $start (; 0 ;) (type $v)
(local $0 i32)
(local $1 f64)
(local $2 i64)
(local $3 f32)
(if
(tee_local $0
(i32.const 0)
@ -71,5 +77,151 @@
)
(unreachable)
)
(set_global $logical/i
(if (result i32)
(tee_local $0
(i32.const 1)
)
(i32.const 2)
(get_local $0)
)
)
(if
(i32.ne
(get_global $logical/i)
(i32.const 2)
)
(unreachable)
)
(set_global $logical/i
(if (result i32)
(tee_local $0
(i32.const 0)
)
(get_local $0)
(i32.const 1)
)
)
(if
(i32.ne
(get_global $logical/i)
(i32.const 1)
)
(unreachable)
)
(set_global $logical/I
(if (result i64)
(i64.ne
(tee_local $2
(i64.const 1)
)
(i64.const 0)
)
(i64.const 2)
(get_local $2)
)
)
(if
(i64.ne
(get_global $logical/I)
(i64.const 2)
)
(unreachable)
)
(set_global $logical/I
(if (result i64)
(i64.ne
(tee_local $2
(i64.const 0)
)
(i64.const 0)
)
(get_local $2)
(i64.const 1)
)
)
(if
(i64.ne
(get_global $logical/I)
(i64.const 1)
)
(unreachable)
)
(set_global $logical/f
(if (result f32)
(f32.ne
(tee_local $3
(f32.const 1)
)
(f32.const 0)
)
(f32.const 2)
(get_local $3)
)
)
(if
(f32.ne
(get_global $logical/f)
(f32.const 2)
)
(unreachable)
)
(set_global $logical/f
(if (result f32)
(f32.ne
(tee_local $3
(f32.const 0)
)
(f32.const 0)
)
(get_local $3)
(f32.const 1)
)
)
(if
(f32.ne
(get_global $logical/f)
(f32.const 1)
)
(unreachable)
)
(set_global $logical/F
(if (result f64)
(f64.ne
(tee_local $1
(f64.const 1)
)
(f64.const 0)
)
(f64.const 2)
(get_local $1)
)
)
(if
(f64.ne
(get_global $logical/F)
(f64.const 2)
)
(unreachable)
)
(set_global $logical/F
(if (result f64)
(f64.ne
(tee_local $1
(f64.const 0)
)
(f64.const 0)
)
(get_local $1)
(f64.const 1)
)
)
(if
(f64.ne
(get_global $logical/F)
(f64.const 1)
)
(unreachable)
)
)
)

View File

@ -5,3 +5,43 @@
1 && 2 || unreachable();
1.0 && 2.0 || unreachable();
let i: i32;
i = 1 && 2;
if (i != 2)
unreachable();
i = 0 || 1;
if (i != 1)
unreachable();
let I: i64;
I = 1 && 2;
if (I != 2)
unreachable();
I = 0 || 1;
if (I != 1)
unreachable();
let f: f32;
f = 1.0 && 2.0;
if (f != 2.0)
unreachable();
f = 0.0 || 1.0;
if (f != 1.0)
unreachable();
let F: f64;
F = 1.0 && 2.0;
if (F != 2.0)
unreachable();
F = 0.0 || 1.0;
if (F != 1.0)
unreachable();

View File

@ -1,5 +1,9 @@
(module
(type $v (func))
(global $logical/i (mut i32) (i32.const 0))
(global $logical/I (mut i64) (i64.const 0))
(global $logical/f (mut f32) (f32.const 0))
(global $logical/F (mut f64) (f64.const 0))
(memory $0 1)
(data (i32.const 4) "\08\00\00\00")
(export "memory" (memory $0))
@ -13,6 +17,14 @@
(local $5 i32)
(local $6 f64)
(local $7 f64)
(local $8 i32)
(local $9 i32)
(local $10 i64)
(local $11 i64)
(local $12 f32)
(local $13 f32)
(local $14 f64)
(local $15 f64)
(drop
(if (result i32)
(tee_local $0
@ -91,6 +103,152 @@
(unreachable)
)
)
(set_global $logical/i
(if (result i32)
(tee_local $8
(i32.const 1)
)
(i32.const 2)
(get_local $8)
)
)
(if
(i32.ne
(get_global $logical/i)
(i32.const 2)
)
(unreachable)
)
(set_global $logical/i
(if (result i32)
(tee_local $9
(i32.const 0)
)
(get_local $9)
(i32.const 1)
)
)
(if
(i32.ne
(get_global $logical/i)
(i32.const 1)
)
(unreachable)
)
(set_global $logical/I
(if (result i64)
(i64.ne
(tee_local $10
(i64.const 1)
)
(i64.const 0)
)
(i64.const 2)
(get_local $10)
)
)
(if
(i64.ne
(get_global $logical/I)
(i64.const 2)
)
(unreachable)
)
(set_global $logical/I
(if (result i64)
(i64.ne
(tee_local $11
(i64.const 0)
)
(i64.const 0)
)
(get_local $11)
(i64.const 1)
)
)
(if
(i64.ne
(get_global $logical/I)
(i64.const 1)
)
(unreachable)
)
(set_global $logical/f
(if (result f32)
(f32.ne
(tee_local $12
(f32.const 1)
)
(f32.const 0)
)
(f32.const 2)
(get_local $12)
)
)
(if
(f32.ne
(get_global $logical/f)
(f32.const 2)
)
(unreachable)
)
(set_global $logical/f
(if (result f32)
(f32.ne
(tee_local $13
(f32.const 0)
)
(f32.const 0)
)
(get_local $13)
(f32.const 1)
)
)
(if
(f32.ne
(get_global $logical/f)
(f32.const 1)
)
(unreachable)
)
(set_global $logical/F
(if (result f64)
(f64.ne
(tee_local $14
(f64.const 1)
)
(f64.const 0)
)
(f64.const 2)
(get_local $14)
)
)
(if
(f64.ne
(get_global $logical/F)
(f64.const 2)
)
(unreachable)
)
(set_global $logical/F
(if (result f64)
(f64.ne
(tee_local $15
(f64.const 0)
)
(f64.const 0)
)
(get_local $15)
(f64.const 1)
)
)
(if
(f64.ne
(get_global $logical/F)
(f64.const 1)
)
(unreachable)
)
)
)
(;
@ -118,6 +276,10 @@
sizeof
load
store
logical/i
logical/I
logical/f
logical/F
[program.exports]
;)