This commit is contained in:
Michal Moskal 2015-10-19 23:08:05 -07:00
Родитель 991de5a045
Коммит 7a073cd014
3 изменённых файлов: 97 добавлений и 27 удалений

Просмотреть файл

@ -1816,6 +1816,7 @@ module TDev.AST {
public _isActionTypeDef:boolean;
public _compilerInlineAction:InlineAction;
public _compilerParentAction:Action; // this is only set for synthetic actions created in compiler for lambda expressions
public _compilerInlineBody:Stmt;
public _skipIntelliProfile:boolean;
public allLocals:LocalDef[];
public accept(v:NodeVisitor) { return v.visitAction(this); }
@ -1855,6 +1856,13 @@ module TDev.AST {
return res
}
public getShimName():string
{
var shm = /{shim:([^{}]*)}/.exec(this.getDescription())
if (shm) return shm[1]
return null
}
public getFlags()
{
var flags = !this.isAtomic ? PropertyFlags.Async : PropertyFlags.None

Просмотреть файл

@ -2,7 +2,7 @@
// TODO events and async
// Next available error: TD212:
// Next available error: TD214:
module TDev.AST
{
@ -96,7 +96,7 @@ module TDev.AST
private isTopExpr = false;
static lastStoreLocalsAt:ExprHolder;
static lintThumb : (asm:string, err:(msg:string) => void) => void;
static lintThumb : (a:Action, asm:string, err:(msg:string) => void) => void;
constructor() {
super()
@ -864,7 +864,7 @@ module TDev.AST
node.clearError();
this.actionSection = ActionSection.Normal;
this.inAtomic = node.isAtomic;
this.inShim = this.topApp.entireShim || /{shim:.*}/.test(node.getDescription())
this.inShim = this.topApp.entireShim || node.getShimName() != null;
this.scope(() => {
// TODO in - read-only?
@ -1778,8 +1778,11 @@ module TDev.AST
break;
case "thumb":
if (!checkArgumentCount(2)) return;
if (!this.inShim)
this.markError(t, lf("TD213: app->thumb only supported inside of {shim:}"))
this.currentAction.getOutParameters().forEach(p => this.recordLocalWrite(p.local))
if (TypeChecker.lintThumb)
TypeChecker.lintThumb(t.args[1].getStringLiteral(), e => this.markError(t, e))
TypeChecker.lintThumb(this.currentAction, t.args[1].getStringLiteral(), e => this.markError(t, e))
break;
case "import":
if (!checkArgumentCount(4)) return;

Просмотреть файл

@ -745,8 +745,16 @@ module TDev.AST.Bytecode
{
useAction(a:Action)
{
if (/{shim:.*}/.test(a.getDescription()))
return
if (a.getShimName() != null && !a._compilerInlineBody) {
a.body.stmts.forEach(s => {
var str = AST.getEmbeddedLangaugeToken(s)
if (str && (<ExprStmt>s).expr.parsed.getCalledProperty().getName() == "thumb") {
a._compilerInlineBody = s;
}
})
if (!a._compilerInlineBody)
return
}
super.useAction(a)
}
}
@ -948,6 +956,11 @@ module TDev.AST.Bytecode
this.proc.emit("push {r1}");
}
reportError(msg:string)
{
Util.userError(msg)
}
handleActionCall(e:Call)
{
var aa = e.calledExtensionAction() || e.calledAction()
@ -962,15 +975,15 @@ module TDev.AST.Bytecode
Util.assert(args.length == aa.getInParameters().length)
var a:Action = aa._compilerInfo || aa
var shm = /{shim:([^{}]*)}/.exec(a.getDescription())
var shm = a.getShimName();
var hasret = !!aa.getOutParameters()[0]
if (shm && shm[1] == "TD_NOOP") {
if (shm == "TD_NOOP") {
Util.assert(!hasret)
return
}
if (shm && /^micro_bit::(createImage|showAnimation|showLeds)$/.test(shm[1])) {
if (/^micro_bit::(createImage|showAnimation|showLeds)$/.test(shm)) {
Util.assert(args[0].getLiteral() != null)
this.emitImageLiteral(args[0].getLiteral())
args.shift()
@ -982,25 +995,41 @@ module TDev.AST.Bytecode
}
if (shm) {
if (shm != null) {
var mask = this.getMask(args)
var msg = "{shim:" + shm[1] + "} from " + a.getName()
if (!shm[1])
Util.oops("called " + msg)
var msg = "{shim:" + shm + "} from " + a.getName()
if (!shm)
Util.oops("called " + msg + " (with empty {shim:}")
var inf = lookupFunc(shm[1])
var inf = lookupFunc(shm)
if (!inf)
Util.oops("no such " + msg)
if (!hasret) {
Util.assert(inf.type == "P", "expecting procedure for " + msg);
if (a._compilerInlineBody) {
if (inf)
this.reportError(lf("app->thumb inline body not allowed in {shim:{0}} (already defined in runtime)", shm))
funcInfo[shm] = {
type: hasret ? "F" : "P",
args: a.getInParameters().length,
idx: 0,
value: 0
}
try {
this.proc.emitCall(shm, mask)
} finally {
delete funcInfo[shm]
}
} else {
Util.assert(inf.type == "F", "expecting function for " + msg);
}
Util.assert(args.length == inf.args, "argument number mismatch: " + args.length + " vs " + inf.args + " in " + msg)
if (!inf)
Util.oops("no such " + msg)
this.proc.emitCall(shm[1], mask)
if (!hasret) {
Util.assert(inf.type == "P", "expecting procedure for " + msg);
} else {
Util.assert(inf.type == "F", "expecting function for " + msg);
}
Util.assert(args.length == inf.args, "argument number mismatch: " + args.length + " vs " + inf.args + " in " + msg)
this.proc.emitCall(shm, mask)
}
} else {
this.proc.emit("bl " + this.procIndex(a).label)
if (args.length > 0) {
@ -1395,6 +1424,15 @@ module TDev.AST.Bytecode
this.proc = this.procIndex(a);
if (a.getShimName() != null) {
var body = AST.getEmbeddedLangaugeToken(a._compilerInlineBody)
Util.assert(body != null)
Util.assert(body.getStringLiteral() != null)
this.proc.emit(body.getStringLiteral())
this.proc.emit("@stackempty func");
return
}
var ret = this.proc.mkLabel("actret")
a._compilerBreakLabel = ret;
this.dispatch(a.body)
@ -1461,6 +1499,25 @@ module TDev.AST.Bytecode
p.action = a;
this.binary.addProc(p)
var shimname = a.getShimName()
if (shimname != null) {
Util.assert(!!a._compilerInlineBody)
if (!/^\w+$/.test(shimname))
this.reportError(lf("invalid inline shim name: {shim:{0}}", shimname))
if (a.getInParameters().length > 4)
this.reportError(lf("inline shims support only up to 4 arguments"));
this.proc.label = shimname
this.proc.emit(".section code");
this.proc.emitLbl(this.proc.label);
this.proc.emit("@stackmark func");
return
}
var inparms = a.getInParameters().map(p => p.local)
this.proc.args = inparms.map((p, i) => {
var l = new Location(i, p);
@ -1477,6 +1534,7 @@ module TDev.AST.Bytecode
this.proc.pushLocals();
visitStmts(a.body, s => {
if (s instanceof ExprStmt) {
var ai = (<ExprStmt>s).expr.assignmentInfo()
if (ai) {
@ -1547,13 +1605,13 @@ module TDev.AST.Bytecode
}
}
function lintThumb(asm:string, err:(msg:string) => void)
function lintThumb(act:Action, asm:string, err:(msg:string) => void)
{
setup();
var code =
".section code\n" +
"@stackmark base\n" +
"_start:\n" +
act.getShimName() + ":\n" +
asm + "\n" +
"@stackempty base\n"
var b = new Thumb.Binary();
@ -1563,14 +1621,15 @@ module TDev.AST.Bytecode
if (b.errors.length > 0) {
b.errors.forEach(e => console.log(e.message))
err(b.errors.map(e => e.message).join("\n"))
err(lf("TD212: thumb assembler error") + "\n" +
b.errors.map(e => e.message).join("\n"))
}
}
TypeChecker.lintThumb = lintThumb;
function asmline(s:string)
{
if (!/:$/.test(s))
if (!/(^\s)|(:$)/.test(s))
s = " " + s
return s + "\n"
}