Initial import.
This commit is contained in:
commit
3210f38e04
292 changed files with 58526 additions and 0 deletions
112
T0/BlobWriter.cs
Normal file
112
T0/BlobWriter.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
/*
|
||||
* A simple class for writing out bytes as hexadecimal constants or
|
||||
* explicit expressions for the initializer of a C array of 'unsigned
|
||||
* char'. It starts every line with a given number of tabs, and aims at
|
||||
* keeping lines below a given threshold (each indentation tab counts as
|
||||
* 8 characters). An explicit newline is inserted before the first
|
||||
* element, and commas are used as separators.
|
||||
*/
|
||||
|
||||
class BlobWriter {
|
||||
|
||||
TextWriter w;
|
||||
int maxLineLen;
|
||||
int indent;
|
||||
int lineLen;
|
||||
|
||||
/*
|
||||
* Create a new instance. 'maxLineLen' is in characters, and
|
||||
* 'indent' is the number of tab characters at the start of
|
||||
* each line.
|
||||
*/
|
||||
internal BlobWriter(TextWriter w, int maxLineLen, int indent)
|
||||
{
|
||||
this.w = w;
|
||||
this.maxLineLen = maxLineLen;
|
||||
this.indent = indent;
|
||||
lineLen = -1;
|
||||
}
|
||||
|
||||
void DoNL()
|
||||
{
|
||||
w.WriteLine();
|
||||
for (int i = 0; i < indent; i ++) {
|
||||
w.Write('\t');
|
||||
}
|
||||
lineLen = (indent << 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a new byte value; it will be converted to an hexadecimal
|
||||
* constant in the output.
|
||||
*/
|
||||
internal void Append(byte b)
|
||||
{
|
||||
if (lineLen < 0) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(',');
|
||||
lineLen ++;
|
||||
if ((lineLen + 5) > maxLineLen) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(' ');
|
||||
lineLen ++;
|
||||
}
|
||||
}
|
||||
w.Write("0x{0:X2}", b);
|
||||
lineLen += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a C expression, which will be used as is. The expression
|
||||
* may resolve to several bytes if it uses internal commas. The
|
||||
* writer will try to honour the expected line length, but it
|
||||
* won't insert a newline character inside the expression.
|
||||
*/
|
||||
internal void Append(string expr)
|
||||
{
|
||||
if (lineLen < 0) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(',');
|
||||
lineLen ++;
|
||||
if ((lineLen + 1 + expr.Length) > maxLineLen) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(' ');
|
||||
lineLen ++;
|
||||
}
|
||||
}
|
||||
w.Write("{0}", expr);
|
||||
lineLen += expr.Length;
|
||||
}
|
||||
}
|
||||
181
T0/CPU.cs
Normal file
181
T0/CPU.cs
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Execution of code during compilation is done in a virtual CPU
|
||||
* incarnated by this class, that contains the relevant registers.
|
||||
*
|
||||
* Accesses to the data on the stack are mapped to accesses to an
|
||||
* internal array, with no explicit control on boundaries. Since the
|
||||
* internal array may be larger than the actual stack contents,
|
||||
* nonsensical accesses may still "work" to some extent. The whole
|
||||
* thing won't derail beyond the CLR VM, though.
|
||||
*/
|
||||
|
||||
class CPU {
|
||||
|
||||
/*
|
||||
* Next instruction to execute is in ipBuf[ipOff].
|
||||
*/
|
||||
internal Opcode[] ipBuf;
|
||||
internal int ipOff;
|
||||
|
||||
/*
|
||||
* stackBuf and stackPtr implement the data stack. The system
|
||||
* stack uses frames; 'rsp' points to the current top frame.
|
||||
*/
|
||||
TValue[] stackBuf;
|
||||
int stackPtr;
|
||||
Frame rsp;
|
||||
|
||||
internal CPU()
|
||||
{
|
||||
stackBuf = new TValue[16];
|
||||
stackPtr = -1;
|
||||
rsp = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter a function, reserving space for 'numLocals' local variables.
|
||||
*/
|
||||
internal void Enter(Opcode[] code, int numLocals)
|
||||
{
|
||||
Frame f = new Frame(rsp, numLocals);
|
||||
rsp = f;
|
||||
f.savedIpBuf = ipBuf;
|
||||
f.savedIpOff = ipOff;
|
||||
ipBuf = code;
|
||||
ipOff = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit the current function.
|
||||
*/
|
||||
internal void Exit()
|
||||
{
|
||||
ipBuf = rsp.savedIpBuf;
|
||||
ipOff = rsp.savedIpOff;
|
||||
rsp = rsp.upper;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current stack depth (number of elements).
|
||||
*/
|
||||
internal int Depth {
|
||||
get {
|
||||
return stackPtr + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a value from the stack.
|
||||
*/
|
||||
internal TValue Pop()
|
||||
{
|
||||
return stackBuf[stackPtr --];
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a value on the stack.
|
||||
*/
|
||||
internal void Push(TValue v)
|
||||
{
|
||||
int len = stackBuf.Length;
|
||||
if (++ stackPtr == len) {
|
||||
TValue[] nbuf = new TValue[len << 1];
|
||||
Array.Copy(stackBuf, 0, nbuf, 0, len);
|
||||
stackBuf = nbuf;
|
||||
}
|
||||
stackBuf[stackPtr] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look at the value at depth 'depth' (0 is top of stack). The
|
||||
* stack is unchanged.
|
||||
*/
|
||||
internal TValue Peek(int depth)
|
||||
{
|
||||
return stackBuf[stackPtr - depth];
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate the stack at depth 'depth': the value at that depth
|
||||
* is moved to the top of stack.
|
||||
*/
|
||||
internal void Rot(int depth)
|
||||
{
|
||||
TValue v = stackBuf[stackPtr - depth];
|
||||
Array.Copy(stackBuf, stackPtr - (depth - 1),
|
||||
stackBuf, stackPtr - depth, depth);
|
||||
stackBuf[stackPtr] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inverse-rotate the stack at depth 'depth': the value at the
|
||||
* top of stack is moved to that depth.
|
||||
*/
|
||||
internal void NRot(int depth)
|
||||
{
|
||||
TValue v = stackBuf[stackPtr];
|
||||
Array.Copy(stackBuf, stackPtr - depth,
|
||||
stackBuf, stackPtr - (depth - 1), depth);
|
||||
stackBuf[stackPtr - depth] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current contents of the local variable 'num'.
|
||||
*/
|
||||
internal TValue GetLocal(int num)
|
||||
{
|
||||
return rsp.locals[num];
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the contents of the local variable 'num'.
|
||||
*/
|
||||
internal void PutLocal(int num, TValue v)
|
||||
{
|
||||
rsp.locals[num] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* The system stack really is a linked list of Frame instances.
|
||||
*/
|
||||
class Frame {
|
||||
|
||||
internal Frame upper;
|
||||
internal Opcode[] savedIpBuf;
|
||||
internal int savedIpOff;
|
||||
internal TValue[] locals;
|
||||
|
||||
internal Frame(Frame upper, int numLocals)
|
||||
{
|
||||
this.upper = upper;
|
||||
locals = new TValue[numLocals];
|
||||
}
|
||||
}
|
||||
}
|
||||
88
T0/CodeElement.cs
Normal file
88
T0/CodeElement.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
abstract class CodeElement {
|
||||
|
||||
internal int Address { get; set; }
|
||||
|
||||
internal int LastLength { get; set; }
|
||||
|
||||
internal abstract int Length { get; }
|
||||
|
||||
internal CodeElement()
|
||||
{
|
||||
Address = -1;
|
||||
}
|
||||
|
||||
internal virtual void SetJumpTarget(CodeElement target)
|
||||
{
|
||||
throw new Exception("Code element accepts no target");
|
||||
}
|
||||
|
||||
internal abstract int Encode(BlobWriter bw);
|
||||
|
||||
internal static int Encode7EUnsigned(uint val, BlobWriter bw)
|
||||
{
|
||||
int len = 1;
|
||||
for (uint w = val; w >= 0x80; w >>= 7) {
|
||||
len ++;
|
||||
}
|
||||
if (bw != null) {
|
||||
for (int k = (len - 1) * 7; k >= 0; k -= 7) {
|
||||
int x = (int)(val >> k) & 0x7F;
|
||||
if (k > 0) {
|
||||
x |= 0x80;
|
||||
}
|
||||
bw.Append((byte)x);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
internal static int Encode7ESigned(int val, BlobWriter bw)
|
||||
{
|
||||
int len = 1;
|
||||
if (val < 0) {
|
||||
for (int w = val; w < -0x40; w >>= 7) {
|
||||
len ++;
|
||||
}
|
||||
} else {
|
||||
for (int w = val; w >= 0x40; w >>= 7) {
|
||||
len ++;
|
||||
}
|
||||
}
|
||||
if (bw != null) {
|
||||
for (int k = (len - 1) * 7; k >= 0; k -= 7) {
|
||||
int x = (int)(val >> k) & 0x7F;
|
||||
if (k > 0) {
|
||||
x |= 0x80;
|
||||
}
|
||||
bw.Append((byte)x);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
78
T0/CodeElementJump.cs
Normal file
78
T0/CodeElementJump.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementJump : CodeElement {
|
||||
|
||||
uint jumpType;
|
||||
CodeElement target;
|
||||
|
||||
internal CodeElementJump(uint jumpType)
|
||||
{
|
||||
this.jumpType = jumpType;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
int len = Encode7EUnsigned(jumpType, null);
|
||||
int joff = JumpOff;
|
||||
if (joff == Int32.MinValue) {
|
||||
len ++;
|
||||
} else {
|
||||
len += Encode7ESigned(joff, null);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void SetJumpTarget(CodeElement target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
int JumpOff {
|
||||
get {
|
||||
if (target == null || Address < 0 || target.Address < 0)
|
||||
{
|
||||
return Int32.MinValue;
|
||||
} else {
|
||||
return target.Address - (Address + LastLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
if (bw == null) {
|
||||
return Length;
|
||||
}
|
||||
int len = Encode7EUnsigned(jumpType, bw);
|
||||
int joff = JumpOff;
|
||||
if (joff == Int32.MinValue) {
|
||||
throw new Exception("Unresolved addresses");
|
||||
}
|
||||
return len + Encode7ESigned(joff, bw);
|
||||
}
|
||||
}
|
||||
46
T0/CodeElementUInt.cs
Normal file
46
T0/CodeElementUInt.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUInt : CodeElement {
|
||||
|
||||
uint val;
|
||||
|
||||
internal CodeElementUInt(uint val) : base()
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val, null);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
return Encode7EUnsigned(val, bw);
|
||||
}
|
||||
}
|
||||
56
T0/CodeElementUIntExpr.cs
Normal file
56
T0/CodeElementUIntExpr.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntExpr : CodeElement {
|
||||
|
||||
uint val;
|
||||
TPointerExpr cx;
|
||||
int off;
|
||||
|
||||
internal CodeElementUIntExpr(uint val,
|
||||
TPointerExpr cx, int off) : base()
|
||||
{
|
||||
this.val = val;
|
||||
this.cx = cx;
|
||||
this.off = off;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val, null)
|
||||
+ (cx.GetMaxBitLength(off) + 6) / 7;
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
int len1 = Encode7EUnsigned(val, bw);
|
||||
int len2 = (cx.GetMaxBitLength(off) + 6) / 7;
|
||||
bw.Append(String.Format("T0_INT{0}({1})",
|
||||
len2, cx.ToCExpr(off)));
|
||||
return len1 + len2;
|
||||
}
|
||||
}
|
||||
51
T0/CodeElementUIntInt.cs
Normal file
51
T0/CodeElementUIntInt.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntInt : CodeElement {
|
||||
|
||||
uint val1;
|
||||
int val2;
|
||||
|
||||
internal CodeElementUIntInt(uint val1, int val2) : base()
|
||||
{
|
||||
this.val1 = val1;
|
||||
this.val2 = val2;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val1, null)
|
||||
+ Encode7ESigned(val2, null);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
int len = Encode7EUnsigned(val1, bw);
|
||||
len += Encode7ESigned(val2, bw);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
50
T0/CodeElementUIntUInt.cs
Normal file
50
T0/CodeElementUIntUInt.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntUInt : CodeElement {
|
||||
|
||||
uint val1, val2;
|
||||
|
||||
internal CodeElementUIntUInt(uint val1, uint val2) : base()
|
||||
{
|
||||
this.val1 = val1;
|
||||
this.val2 = val2;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val1, null)
|
||||
+ Encode7EUnsigned(val2, null);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
int len = Encode7EUnsigned(val1, bw);
|
||||
len += Encode7EUnsigned(val2, bw);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
198
T0/ConstData.cs
Normal file
198
T0/ConstData.cs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
class ConstData {
|
||||
|
||||
internal long ID { get; private set; }
|
||||
internal int Address { get; set; }
|
||||
internal int Length {
|
||||
get {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] buf;
|
||||
int len;
|
||||
|
||||
internal ConstData(T0Comp ctx)
|
||||
{
|
||||
ID = ctx.NextBlobID();
|
||||
buf = new byte[4];
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void Expand(int elen)
|
||||
{
|
||||
int tlen = len + elen;
|
||||
if (tlen > buf.Length) {
|
||||
int nlen = Math.Max(buf.Length << 1, tlen);
|
||||
byte[] nbuf = new byte[nlen];
|
||||
Array.Copy(buf, 0, nbuf, 0, len);
|
||||
buf = nbuf;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Add8(byte b)
|
||||
{
|
||||
Expand(1);
|
||||
buf[len ++] = b;
|
||||
}
|
||||
|
||||
internal void Add16(int x)
|
||||
{
|
||||
Expand(2);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void Add24(int x)
|
||||
{
|
||||
Expand(3);
|
||||
buf[len ++] = (byte)(x >> 16);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void Add32(int x)
|
||||
{
|
||||
Expand(4);
|
||||
buf[len ++] = (byte)(x >> 24);
|
||||
buf[len ++] = (byte)(x >> 16);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void AddString(string s)
|
||||
{
|
||||
byte[] sd = Encoding.UTF8.GetBytes(s);
|
||||
Expand(sd.Length + 1);
|
||||
Array.Copy(sd, 0, buf, len, sd.Length);
|
||||
buf[len + sd.Length] = 0;
|
||||
len += sd.Length + 1;
|
||||
}
|
||||
|
||||
void CheckIndex(int off, int dlen)
|
||||
{
|
||||
if (off < 0 || off > (len - dlen)) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Set8(int off, byte v)
|
||||
{
|
||||
CheckIndex(off, 1);
|
||||
buf[off] = v;
|
||||
}
|
||||
|
||||
internal byte Read8(int off)
|
||||
{
|
||||
CheckIndex(off, 1);
|
||||
return buf[off];
|
||||
}
|
||||
|
||||
internal int Read16(int off)
|
||||
{
|
||||
CheckIndex(off, 2);
|
||||
return (buf[off] << 8) | buf[off + 1];
|
||||
}
|
||||
|
||||
internal int Read24(int off)
|
||||
{
|
||||
CheckIndex(off, 3);
|
||||
return (buf[off] << 16) | (buf[off + 1] << 8) | buf[off + 2];
|
||||
}
|
||||
|
||||
internal int Read32(int off)
|
||||
{
|
||||
CheckIndex(off, 4);
|
||||
return (buf[off] << 24) | (buf[off + 1] << 16)
|
||||
| (buf[off + 2] << 8) | buf[off + 3];
|
||||
}
|
||||
|
||||
internal string ToString(int off)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
int x = DecodeUTF8(ref off);
|
||||
if (x == 0) {
|
||||
return sb.ToString();
|
||||
}
|
||||
if (x < 0x10000) {
|
||||
sb.Append((char)x);
|
||||
} else {
|
||||
x -= 0x10000;
|
||||
sb.Append((char)(0xD800 + (x >> 10)));
|
||||
sb.Append((char)(0xDC00 + (x & 0x3FF)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DecodeUTF8(ref int off)
|
||||
{
|
||||
if (off >= len) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
int x = buf[off ++];
|
||||
if (x < 0xC0 || x > 0xF7) {
|
||||
return x;
|
||||
}
|
||||
int elen, acc;
|
||||
if (x >= 0xF0) {
|
||||
elen = 3;
|
||||
acc = x & 0x07;
|
||||
} else if (x >= 0xE0) {
|
||||
elen = 2;
|
||||
acc = x & 0x0F;
|
||||
} else {
|
||||
elen = 1;
|
||||
acc = x & 0x1F;
|
||||
}
|
||||
if (off + elen > len) {
|
||||
return x;
|
||||
}
|
||||
for (int i = 0; i < elen; i ++) {
|
||||
int y = buf[off + i];
|
||||
if (y < 0x80 || y >= 0xC0) {
|
||||
return x;
|
||||
}
|
||||
acc = (acc << 6) + (y & 0x3F);
|
||||
}
|
||||
if (acc > 0x10FFFF) {
|
||||
return x;
|
||||
}
|
||||
off += elen;
|
||||
return acc;
|
||||
}
|
||||
|
||||
internal void Encode(BlobWriter bw)
|
||||
{
|
||||
for (int i = 0; i < len; i ++) {
|
||||
bw.Append(buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
117
T0/Opcode.cs
Normal file
117
T0/Opcode.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
abstract class Opcode {
|
||||
|
||||
internal Opcode()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute this opcode.
|
||||
*/
|
||||
internal abstract void Run(CPU cpu);
|
||||
|
||||
/*
|
||||
* Resolve the target (word reference) for this opcode.
|
||||
*/
|
||||
internal virtual void ResolveTarget(Word target)
|
||||
{
|
||||
throw new Exception("Not a call opcode");
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the jump offset for this opcode. Displacement is
|
||||
* relative to the address of the opcode that immediately follows
|
||||
* the jump code; thus, 0 implies no jump at all.
|
||||
*/
|
||||
internal virtual void ResolveJump(int disp)
|
||||
{
|
||||
throw new Exception("Not a jump opcode");
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Word that this opcode references; this can happen
|
||||
* only with "call" and "const" opcodes. For all other opcodes,
|
||||
* this method returns null.
|
||||
*/
|
||||
internal virtual Word GetReference(T0Comp ctx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the data block that this opcode references; this can happen
|
||||
* only with "const" opcodes. For all other opcodes, this method
|
||||
* returns null.
|
||||
*/
|
||||
internal virtual ConstData GetDataBlock(T0Comp ctx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether this opcode may "fall through", i.e. execution
|
||||
* may at least potentially proceed to the next opcode.
|
||||
*/
|
||||
internal virtual bool MayFallThrough {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get jump displacement. For non-jump opcodes, this returns 0.
|
||||
*/
|
||||
internal virtual int JumpDisp {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get stack effect for this opcode (number of elements added to
|
||||
* the stack, could be negative). For OpcodeCall, this returns
|
||||
* 0.
|
||||
*/
|
||||
internal virtual int StackAction {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract CodeElement ToCodeElement();
|
||||
|
||||
/*
|
||||
* This method is called for the CodeElement corresponding to
|
||||
* this opcode, at gcode[off]; it is used to compute actual
|
||||
* byte jump offsets when converting code to C.
|
||||
*/
|
||||
internal virtual void FixUp(CodeElement[] gcode, int off)
|
||||
{
|
||||
}
|
||||
}
|
||||
71
T0/OpcodeCall.cs
Normal file
71
T0/OpcodeCall.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeCall : Opcode {
|
||||
|
||||
Word target;
|
||||
|
||||
internal OpcodeCall() : this(null)
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeCall(Word target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
internal override void ResolveTarget(Word target)
|
||||
{
|
||||
if (this.target != null) {
|
||||
throw new Exception("Opcode already resolved");
|
||||
}
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
target.Run(cpu);
|
||||
}
|
||||
|
||||
internal override Word GetReference(T0Comp ctx)
|
||||
{
|
||||
if (target == null) {
|
||||
throw new Exception("Unresolved call target");
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUInt((uint)target.Slot);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "call " + (target == null ? "UNRESOLVED" : target.Name);
|
||||
}
|
||||
}
|
||||
95
T0/OpcodeConst.cs
Normal file
95
T0/OpcodeConst.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeConst : Opcode {
|
||||
|
||||
TValue val;
|
||||
|
||||
internal OpcodeConst(TValue val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Push(val);
|
||||
}
|
||||
|
||||
internal override Word GetReference(T0Comp ctx)
|
||||
{
|
||||
TPointerXT xt = val.ptr as TPointerXT;
|
||||
if (xt == null) {
|
||||
return null;
|
||||
}
|
||||
xt.Resolve(ctx);
|
||||
return xt.Target;
|
||||
}
|
||||
|
||||
internal override ConstData GetDataBlock(T0Comp ctx)
|
||||
{
|
||||
TPointerBlob bp = val.ptr as TPointerBlob;
|
||||
return bp == null ? null : bp.Blob;
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
if (val.ptr == null) {
|
||||
return new CodeElementUIntInt(1, val.Int);
|
||||
}
|
||||
TPointerXT xt = val.ptr as TPointerXT;
|
||||
if (xt != null) {
|
||||
if (val.x != 0) {
|
||||
throw new Exception(
|
||||
"Cannot compile XT: non-zero offset");
|
||||
}
|
||||
return new CodeElementUIntInt(1, xt.Target.Slot);
|
||||
}
|
||||
TPointerBlob bp = val.ptr as TPointerBlob;
|
||||
if (bp != null) {
|
||||
return new CodeElementUIntInt(1,
|
||||
val.x + bp.Blob.Address);
|
||||
}
|
||||
TPointerExpr cx = val.ptr as TPointerExpr;
|
||||
if (cx != null) {
|
||||
return new CodeElementUIntExpr(1, cx, val.x);
|
||||
}
|
||||
throw new Exception(String.Format(
|
||||
"Cannot embed constant (type = {0})",
|
||||
val.ptr.GetType().FullName));
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "const " + val.ToString();
|
||||
}
|
||||
}
|
||||
57
T0/OpcodeGetLocal.cs
Normal file
57
T0/OpcodeGetLocal.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeGetLocal : Opcode {
|
||||
|
||||
int num;
|
||||
|
||||
internal OpcodeGetLocal(int num)
|
||||
{
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Push(cpu.GetLocal(num));
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUIntUInt(2, (uint)num);
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "getlocal " + num;
|
||||
}
|
||||
}
|
||||
64
T0/OpcodeJump.cs
Normal file
64
T0/OpcodeJump.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
abstract class OpcodeJump : Opcode {
|
||||
|
||||
int disp;
|
||||
|
||||
internal OpcodeJump() : this(Int32.MinValue)
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJump(int disp)
|
||||
{
|
||||
this.disp = disp;
|
||||
}
|
||||
|
||||
internal override int JumpDisp {
|
||||
get {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.ipOff += disp;
|
||||
}
|
||||
|
||||
internal override void ResolveJump(int disp)
|
||||
{
|
||||
if (this.disp != Int32.MinValue) {
|
||||
throw new Exception("Jump already resolved");
|
||||
}
|
||||
this.disp = disp;
|
||||
}
|
||||
|
||||
internal override void FixUp(CodeElement[] gcode, int off)
|
||||
{
|
||||
gcode[off].SetJumpTarget(gcode[off + 1 + disp]);
|
||||
}
|
||||
}
|
||||
65
T0/OpcodeJumpIf.cs
Normal file
65
T0/OpcodeJumpIf.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpIf : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpIf() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpIf(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
TValue v = cpu.Pop();
|
||||
if (v.Bool) {
|
||||
base.Run(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(5);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jumpif UNRESOLVED";
|
||||
} else {
|
||||
return "jumpif disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
T0/OpcodeJumpIfNot.cs
Normal file
65
T0/OpcodeJumpIfNot.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpIfNot : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpIfNot() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpIfNot(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
TValue v = cpu.Pop();
|
||||
if (!v.Bool) {
|
||||
base.Run(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(6);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jumpifnot UNRESOLVED";
|
||||
} else {
|
||||
return "jumpifnot disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
||||
61
T0/OpcodeJumpUncond.cs
Normal file
61
T0/OpcodeJumpUncond.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpUncond : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpUncond() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpUncond(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Unconditional jumps do not "fall through" unless they
|
||||
* happen to be a jump to the next instruction...
|
||||
*/
|
||||
internal override bool MayFallThrough {
|
||||
get {
|
||||
return JumpDisp == 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(4);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jump UNRESOLVED";
|
||||
} else {
|
||||
return "jump disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
T0/OpcodePutLocal.cs
Normal file
57
T0/OpcodePutLocal.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodePutLocal : Opcode {
|
||||
|
||||
int num;
|
||||
|
||||
internal OpcodePutLocal(int num)
|
||||
{
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.PutLocal(num, cpu.Pop());
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUIntUInt(3, (uint)num);
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "putlocal " + num;
|
||||
}
|
||||
}
|
||||
50
T0/OpcodeRet.cs
Normal file
50
T0/OpcodeRet.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeRet : Opcode {
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Exit();
|
||||
}
|
||||
|
||||
internal override bool MayFallThrough {
|
||||
get {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUInt(0);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "ret";
|
||||
}
|
||||
}
|
||||
129
T0/SType.cs
Normal file
129
T0/SType.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
using System;
|
||||
|
||||
/*
|
||||
* This structure contains the stack effect of a word: number of stack
|
||||
* element consumed on input, and number of stack element produced on
|
||||
* output.
|
||||
*/
|
||||
|
||||
struct SType {
|
||||
|
||||
/*
|
||||
* Get number of stack elements consumed on input; this is -1 if
|
||||
* the stack effect is not known.
|
||||
*/
|
||||
internal int DataIn {
|
||||
get {
|
||||
return din;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get number of stack elements produced on output; this is -1 if
|
||||
* either the stack effect is not known, or if the word never
|
||||
* exits.
|
||||
*/
|
||||
internal int DataOut {
|
||||
get {
|
||||
return dout;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell whether the stack effect is known.
|
||||
*/
|
||||
internal bool IsKnown {
|
||||
get {
|
||||
return din >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell whether the stack effect is known and the word never exits.
|
||||
*/
|
||||
internal bool NoExit {
|
||||
get {
|
||||
return din >= 0 && dout < 0;
|
||||
}
|
||||
}
|
||||
|
||||
int din, dout;
|
||||
|
||||
internal SType(int din, int dout)
|
||||
{
|
||||
if (din < 0) {
|
||||
din = -1;
|
||||
}
|
||||
if (dout < 0) {
|
||||
dout = -1;
|
||||
}
|
||||
this.din = din;
|
||||
this.dout = dout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special value for the unknown stack effect.
|
||||
*/
|
||||
internal static SType UNKNOWN = new SType(-1, -1);
|
||||
|
||||
/*
|
||||
* Constant for the "blank stack effect".
|
||||
*/
|
||||
internal static SType BLANK = new SType(0, 0);
|
||||
|
||||
public static bool operator ==(SType s1, SType s2)
|
||||
{
|
||||
return s1.din == s2.din && s1.dout == s2.dout;
|
||||
}
|
||||
|
||||
public static bool operator !=(SType s1, SType s2)
|
||||
{
|
||||
return s1.din != s2.din || s1.dout != s2.dout;
|
||||
}
|
||||
|
||||
public override bool Equals(Object obj)
|
||||
{
|
||||
return (obj is SType) && ((SType)obj == this);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return din * 31 + dout * 17;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (!IsKnown) {
|
||||
return "UNKNOWN";
|
||||
} else if (NoExit) {
|
||||
return string.Format("in:{0},noexit", din);
|
||||
} else {
|
||||
return string.Format("in:{0},out:{1}", din, dout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether this stack effect is a sub-effect of the provided
|
||||
* stack effect s. Stack effect s1 is a sub-effect of stack-effect
|
||||
* s2 if any of the following holds:
|
||||
* -- s1 and s2 are known, s1.din <= s2.din and s1 does not exit.
|
||||
* -- s1 and s2 are known, s1.din <= s2.din, s1 and s2 exit,
|
||||
* and s1.din - s1.dout == s2.din - s2.dout.
|
||||
*/
|
||||
internal bool IsSubOf(SType s)
|
||||
{
|
||||
if (!IsKnown || !s.IsKnown) {
|
||||
return false;
|
||||
}
|
||||
if (din > s.din) {
|
||||
return false;
|
||||
}
|
||||
if (NoExit) {
|
||||
return true;
|
||||
}
|
||||
if (s.NoExit) {
|
||||
return false;
|
||||
}
|
||||
return (din - dout) == (s.din - s.dout);
|
||||
}
|
||||
}
|
||||
2070
T0/T0Comp.cs
Normal file
2070
T0/T0Comp.cs
Normal file
File diff suppressed because it is too large
Load diff
64
T0/TPointerBase.cs
Normal file
64
T0/TPointerBase.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerBase {
|
||||
|
||||
/* obsolete
|
||||
internal virtual TValue Get(TValue vp)
|
||||
{
|
||||
throw new Exception(
|
||||
"cannot get values from this pointer");
|
||||
}
|
||||
|
||||
internal virtual void Set(TValue vp, TValue nval)
|
||||
{
|
||||
throw new Exception(
|
||||
"cannot set values to this pointer");
|
||||
}
|
||||
*/
|
||||
|
||||
internal virtual bool ToBool(TValue vp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
internal virtual void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
throw new Exception("value is not an xt: " + ToString());
|
||||
}
|
||||
|
||||
internal virtual string ToString(TValue vp)
|
||||
{
|
||||
return String.Format("{0}+{1}",
|
||||
GetType().Name, vp.x);
|
||||
}
|
||||
|
||||
internal virtual bool Equals(TPointerBase tp)
|
||||
{
|
||||
return this == tp;
|
||||
}
|
||||
}
|
||||
75
T0/TPointerBlob.cs
Normal file
75
T0/TPointerBlob.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerBlob : TPointerBase {
|
||||
|
||||
internal ConstData Blob { get; private set; }
|
||||
|
||||
internal TPointerBlob(ConstData cd)
|
||||
{
|
||||
this.Blob = cd;
|
||||
}
|
||||
|
||||
internal TPointerBlob(T0Comp owner, string s)
|
||||
{
|
||||
Blob = new ConstData(owner);
|
||||
Blob.AddString(s);
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override TValue Get8(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read8(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get16(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read16(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get24(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read24(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get32(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read32(vp.x));
|
||||
}
|
||||
*/
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return Blob.ToString(vp.x);
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
TPointerBlob tb = tp as TPointerBlob;
|
||||
return tb != null && Blob == tb.Blob;
|
||||
}
|
||||
}
|
||||
97
T0/TPointerExpr.cs
Normal file
97
T0/TPointerExpr.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class TPointerExpr : TPointerBase {
|
||||
|
||||
string expr;
|
||||
int min, max;
|
||||
|
||||
internal TPointerExpr(string expr, int min, int max)
|
||||
{
|
||||
this.expr = expr;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
internal override bool ToBool(TValue vp)
|
||||
{
|
||||
throw new Exception("Cannot evaluate C-expr at compile time");
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return ToCExpr(vp.x);
|
||||
}
|
||||
|
||||
internal string ToCExpr(int off)
|
||||
{
|
||||
if (off == 0) {
|
||||
return expr;
|
||||
} else if (off > 0) {
|
||||
return String.Format(
|
||||
"(uint32_t)({0}) + {1}", expr, off);
|
||||
} else {
|
||||
return String.Format(
|
||||
"(uint32_t)({0}) - {1}", expr, -(long)off);
|
||||
}
|
||||
}
|
||||
|
||||
internal int GetMaxBitLength(int off)
|
||||
{
|
||||
long rmin = (long)min + off;
|
||||
long rmax = (long)max + off;
|
||||
int numBits = 1;
|
||||
if (rmin < 0) {
|
||||
numBits = Math.Max(numBits, BitLength(rmin));
|
||||
}
|
||||
if (rmax > 0) {
|
||||
numBits = Math.Max(numBits, BitLength(rmax));
|
||||
}
|
||||
return Math.Min(numBits, 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the minimal bit length of a value. This is for a signed
|
||||
* representation: the length includes a sign bit. Thus, the
|
||||
* returned value will be at least 1.
|
||||
*/
|
||||
static int BitLength(long v)
|
||||
{
|
||||
int num = 1;
|
||||
if (v < 0) {
|
||||
while (v != -1) {
|
||||
num ++;
|
||||
v >>= 1;
|
||||
}
|
||||
} else {
|
||||
while (v != 0) {
|
||||
num ++;
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
44
T0/TPointerNull.cs
Normal file
44
T0/TPointerNull.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerNull : TPointerBase {
|
||||
|
||||
internal override bool ToBool(TValue vp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
return tp is TPointerNull;
|
||||
}
|
||||
}
|
||||
73
T0/TPointerXT.cs
Normal file
73
T0/TPointerXT.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerXT : TPointerBase {
|
||||
|
||||
internal string Name {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
internal Word Target {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
internal TPointerXT(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Target = null;
|
||||
}
|
||||
|
||||
internal TPointerXT(Word target)
|
||||
{
|
||||
this.Name = target.Name;
|
||||
this.Target = target;
|
||||
}
|
||||
|
||||
internal void Resolve(T0Comp ctx)
|
||||
{
|
||||
if (Target == null) {
|
||||
Target = ctx.Lookup(Name);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
Resolve(ctx);
|
||||
Target.Run(cpu);
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return String.Format("<'{0}>", Name);
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
TPointerXT tx = tp as TPointerXT;
|
||||
return tx != null && Name == tx.Name;
|
||||
}
|
||||
}
|
||||
231
T0/TValue.cs
Normal file
231
T0/TValue.cs
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Each value is represented with a TValue structure. Integers use the 'x'
|
||||
* field, and 'ptr' is null; for pointers, the 'ptr' field is used, and the
|
||||
* 'x' is then an offset in the object represented by 'ptr'.
|
||||
*/
|
||||
|
||||
struct TValue {
|
||||
|
||||
internal int x;
|
||||
internal TPointerBase ptr;
|
||||
|
||||
internal TValue(int x)
|
||||
{
|
||||
this.x = x;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(uint x)
|
||||
{
|
||||
this.x = (int)x;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(bool b)
|
||||
{
|
||||
this.x = b ? -1 : 0;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(int x, TPointerBase ptr)
|
||||
{
|
||||
this.x = x;
|
||||
this.ptr = ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert this value to a boolean; integer 0 and null pointer are
|
||||
* 'false', other values are 'true'.
|
||||
*/
|
||||
internal bool Bool {
|
||||
get {
|
||||
if (ptr == null) {
|
||||
return x != 0;
|
||||
} else {
|
||||
return ptr.ToBool(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get this value as an integer. Pointers cannot be converted to
|
||||
* integers.
|
||||
*/
|
||||
internal int Int {
|
||||
get {
|
||||
if (ptr == null) {
|
||||
return x;
|
||||
}
|
||||
throw new Exception("not an integer: " + ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get this value as an unsigned integer. This is the integer
|
||||
* value, reduced modulo 2^32 in the 0..2^32-1 range.
|
||||
*/
|
||||
internal uint UInt {
|
||||
get {
|
||||
return (uint)Int;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* String format of integers uses decimal representation. For
|
||||
* pointers, this depends on the pointed-to value.
|
||||
*/
|
||||
public override string ToString()
|
||||
{
|
||||
if (ptr == null) {
|
||||
return String.Format("{0}", x);
|
||||
} else {
|
||||
return ptr.ToString(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this value is an XT, then execute it. Otherwise, an exception
|
||||
* is thrown.
|
||||
*/
|
||||
internal void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
ToXT().Execute(ctx, cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert this value to an XT. On failure, an exception is thrown.
|
||||
*/
|
||||
internal TPointerXT ToXT()
|
||||
{
|
||||
TPointerXT xt = ptr as TPointerXT;
|
||||
if (xt == null) {
|
||||
throw new Exception(
|
||||
"value is not an xt: " + ToString());
|
||||
}
|
||||
return xt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare this value to another.
|
||||
*/
|
||||
internal bool Equals(TValue v)
|
||||
{
|
||||
if (x != v.x) {
|
||||
return false;
|
||||
}
|
||||
if (ptr == v.ptr) {
|
||||
return true;
|
||||
}
|
||||
if (ptr == null || v.ptr == null) {
|
||||
return false;
|
||||
}
|
||||
return ptr.Equals(v.ptr);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(bool val)
|
||||
{
|
||||
return new TValue(val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(sbyte val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(byte val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(short val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(ushort val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(char val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(int val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(uint val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator bool(TValue v)
|
||||
{
|
||||
return v.Bool;
|
||||
}
|
||||
|
||||
public static implicit operator sbyte(TValue v)
|
||||
{
|
||||
return (sbyte)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator byte(TValue v)
|
||||
{
|
||||
return (byte)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator short(TValue v)
|
||||
{
|
||||
return (short)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator ushort(TValue v)
|
||||
{
|
||||
return (ushort)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator char(TValue v)
|
||||
{
|
||||
return (char)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator int(TValue v)
|
||||
{
|
||||
return (int)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator uint(TValue v)
|
||||
{
|
||||
return (uint)v.Int;
|
||||
}
|
||||
}
|
||||
172
T0/Word.cs
Normal file
172
T0/Word.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* A "word" is a function with a name. Words can be either native or
|
||||
* interpreted; native words are implemented as some in-compiler special
|
||||
* code.
|
||||
*
|
||||
* Some native words (not all of them) have a C implementation and can
|
||||
* thus be part of the generated C code. Native words with no C
|
||||
* implementation can be used only during compilation; this is typically
|
||||
* the case for words that support the syntax (e.g. 'if').
|
||||
*/
|
||||
|
||||
abstract class Word {
|
||||
|
||||
/*
|
||||
* The compiler context for this word.
|
||||
*/
|
||||
internal T0Comp TC {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Immediate words are executed immediately when encountered in the
|
||||
* source code, even while compiling another word.
|
||||
*/
|
||||
internal bool Immediate {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each word has a unique name. Names are case-sensitive.
|
||||
*/
|
||||
internal string Name {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Words are allocated slot numbers when output code is generated.
|
||||
*/
|
||||
internal int Slot {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each word may have a known stack effect.
|
||||
*/
|
||||
internal SType StackEffect {
|
||||
get; set;
|
||||
}
|
||||
|
||||
internal Word(T0Comp owner, string name)
|
||||
{
|
||||
TC = owner;
|
||||
Name = name;
|
||||
StackEffect = SType.UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolving a word means looking up all references to external
|
||||
* words.
|
||||
*/
|
||||
internal virtual void Resolve()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute this word. If the word is native, then its code is
|
||||
* run right away; if the word is interpreted, then the entry
|
||||
* sequence is executed.
|
||||
*/
|
||||
internal virtual void Run(CPU cpu)
|
||||
{
|
||||
throw new Exception(String.Format(
|
||||
"cannot run '{0}' at compile-time", Name));
|
||||
}
|
||||
|
||||
/*
|
||||
* All words may have an explicit C implementations. To be part
|
||||
* of the generated C code, a word must either be interpreted,
|
||||
* or have an explicit C implementation, or both.
|
||||
*/
|
||||
internal string CCode {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all words referenced from this one. This implies
|
||||
* resolving the word.
|
||||
*/
|
||||
internal virtual List<Word> GetReferences()
|
||||
{
|
||||
return new List<Word>();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all data blocks directly referenced from this one. This
|
||||
* implies resolving the word.
|
||||
*/
|
||||
internal virtual List<ConstData> GetDataBlocks()
|
||||
{
|
||||
return new List<ConstData>();
|
||||
}
|
||||
|
||||
/*
|
||||
* Produce the code elements for this word.
|
||||
*/
|
||||
internal virtual void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
throw new Exception("Word does not yield code elements");
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute/verify stack effect for this word.
|
||||
*/
|
||||
internal virtual void AnalyseFlow()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Get maximum data stack usage for this word. This is the number
|
||||
* of extra slots that this word may need on the data stack. If
|
||||
* the stack effect is not known, this returns -1.
|
||||
*/
|
||||
internal virtual int MaxDataStack {
|
||||
get {
|
||||
SType se = StackEffect;
|
||||
if (!se.IsKnown) {
|
||||
return -1;
|
||||
}
|
||||
if (se.NoExit) {
|
||||
return 0;
|
||||
} else {
|
||||
return Math.Min(0, se.DataOut - se.DataIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get maximum return stack usage for this word.
|
||||
*/
|
||||
internal virtual int MaxReturnStack {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
385
T0/WordBuilder.cs
Normal file
385
T0/WordBuilder.cs
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* A WordBuilder instance organizes construction of a new interpreted word.
|
||||
*
|
||||
* Opcodes are accumulated with specific methods. A control-flow stack
|
||||
* is maintained to resolve jumps.
|
||||
*
|
||||
* Each instance shall be used for only one word.
|
||||
*/
|
||||
|
||||
class WordBuilder {
|
||||
|
||||
T0Comp TC;
|
||||
string name;
|
||||
int[] cfStack;
|
||||
int cfPtr;
|
||||
List<Opcode> code;
|
||||
List<string> toResolve;
|
||||
Dictionary<string, int> locals;
|
||||
bool jumpToLast;
|
||||
|
||||
internal SType StackEffect {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new instance, with the specified word name.
|
||||
*/
|
||||
internal WordBuilder(T0Comp TC, string name)
|
||||
{
|
||||
this.TC = TC;
|
||||
this.name = name;
|
||||
cfStack = new int[16];
|
||||
cfPtr = -1;
|
||||
code = new List<Opcode>();
|
||||
toResolve = new List<string>();
|
||||
locals = new Dictionary<string, int>();
|
||||
jumpToLast = true;
|
||||
StackEffect = SType.UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the word. The control-flow stack must be empty. A 'ret'
|
||||
* opcode is automatically appended if required.
|
||||
*/
|
||||
internal Word Build()
|
||||
{
|
||||
if (cfPtr != -1) {
|
||||
throw new Exception("control-flow stack is not empty");
|
||||
}
|
||||
if (jumpToLast || code[code.Count - 1].MayFallThrough) {
|
||||
Ret();
|
||||
}
|
||||
Word w = new WordInterpreted(TC, name, locals.Count,
|
||||
code.ToArray(), toResolve.ToArray());
|
||||
w.StackEffect = StackEffect;
|
||||
return w;
|
||||
}
|
||||
|
||||
void Add(Opcode op)
|
||||
{
|
||||
Add(op, null);
|
||||
}
|
||||
|
||||
void Add(Opcode op, string refName)
|
||||
{
|
||||
code.Add(op);
|
||||
toResolve.Add(refName);
|
||||
jumpToLast = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate the control-flow stack at depth 'depth'.
|
||||
*/
|
||||
internal void CSRoll(int depth)
|
||||
{
|
||||
int x = cfStack[cfPtr - depth];
|
||||
Array.Copy(cfStack, cfPtr - (depth - 1),
|
||||
cfStack, cfPtr - depth, depth);
|
||||
cfStack[cfPtr] = x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a copy of the control-flow element at depth 'depth', and
|
||||
* push it on top of the control-flow stack.
|
||||
*/
|
||||
internal void CSPick(int depth)
|
||||
{
|
||||
int x = cfStack[cfPtr - depth];
|
||||
CSPush(x);
|
||||
}
|
||||
|
||||
void CSPush(int x)
|
||||
{
|
||||
int len = cfStack.Length;
|
||||
if (++ cfPtr == len) {
|
||||
int[] ncf = new int[len << 1];
|
||||
Array.Copy(cfStack, 0, ncf, 0, len);
|
||||
cfStack = ncf;
|
||||
}
|
||||
cfStack[cfPtr] = x;
|
||||
}
|
||||
|
||||
int CSPop()
|
||||
{
|
||||
return cfStack[cfPtr --];
|
||||
}
|
||||
|
||||
/*
|
||||
* Push an origin on the control-flow stack, corresponding to the
|
||||
* next opcode to add.
|
||||
*/
|
||||
internal void CSPushOrig()
|
||||
{
|
||||
CSPush(code.Count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a destination on the control-flow stack, corresponding to
|
||||
* the next opcode to add.
|
||||
*/
|
||||
internal void CSPushDest()
|
||||
{
|
||||
CSPush(-code.Count - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop an origin from the control-flow stack. An exception is
|
||||
* thrown if the value is not an origin.
|
||||
*/
|
||||
internal int CSPopOrig()
|
||||
{
|
||||
int x = CSPop();
|
||||
if (x < 0) {
|
||||
throw new Exception("not an origin");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a destination from the control-flow stack. An exception is
|
||||
* thrown if the value is not a destination.
|
||||
*/
|
||||
internal int CSPopDest()
|
||||
{
|
||||
int x = CSPop();
|
||||
if (x >= 0) {
|
||||
throw new Exception("not a destination");
|
||||
}
|
||||
return -x - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "push literal" opcode.
|
||||
*/
|
||||
internal void Literal(TValue v)
|
||||
{
|
||||
Add(new OpcodeConst(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile a "call" by name. This method implements the support
|
||||
* for local variables:
|
||||
*
|
||||
* - If the target is '>' followed by a local variable name, then
|
||||
* a "put local" opcode is added.
|
||||
*
|
||||
* - Otherwise, if the target is a local variable name, then a
|
||||
* "get local" opcode is added.
|
||||
*
|
||||
* - Otherwise, a call to the named word is added. The target name
|
||||
* will be resolved later on (typically, when the word containing
|
||||
* the call opcode is first invoked, or when C code is generated).
|
||||
*/
|
||||
internal void Call(string target)
|
||||
{
|
||||
string lname;
|
||||
bool write;
|
||||
if (target.StartsWith(">")) {
|
||||
lname = target.Substring(1);
|
||||
write = true;
|
||||
} else {
|
||||
lname = target;
|
||||
write = false;
|
||||
}
|
||||
int lnum;
|
||||
if (locals.TryGetValue(lname, out lnum)) {
|
||||
if (write) {
|
||||
Add(new OpcodePutLocal(lnum));
|
||||
} else {
|
||||
Add(new OpcodeGetLocal(lnum));
|
||||
}
|
||||
} else {
|
||||
Add(new OpcodeCall(), target);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode to the designated word.
|
||||
*/
|
||||
internal void CallExt(Word wtarget)
|
||||
{
|
||||
Add(new OpcodeCall(wtarget), null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode to a word which is not currently resolved.
|
||||
* This method ignores local variables.
|
||||
*/
|
||||
internal void CallExt(string target)
|
||||
{
|
||||
Add(new OpcodeCall(), target);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "get local" opcode; the provided local name must already
|
||||
* be defined.
|
||||
*/
|
||||
internal void GetLocal(string name)
|
||||
{
|
||||
int lnum;
|
||||
if (locals.TryGetValue(name, out lnum)) {
|
||||
Add(new OpcodeGetLocal(lnum));
|
||||
} else {
|
||||
throw new Exception("no such local: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "put local" opcode; the provided local name must already
|
||||
* be defined.
|
||||
*/
|
||||
internal void PutLocal(string name)
|
||||
{
|
||||
int lnum;
|
||||
if (locals.TryGetValue(name, out lnum)) {
|
||||
Add(new OpcodePutLocal(lnum));
|
||||
} else {
|
||||
throw new Exception("no such local: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a new local name.
|
||||
*/
|
||||
internal void DefLocal(string lname)
|
||||
{
|
||||
if (locals.ContainsKey(lname)) {
|
||||
throw new Exception(String.Format(
|
||||
"local already defined: {0}", lname));
|
||||
}
|
||||
locals[lname] = locals.Count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode whose target is an XT value (which may be
|
||||
* resolved or as yet unresolved).
|
||||
*/
|
||||
internal void Call(TPointerXT xt)
|
||||
{
|
||||
if (xt.Target == null) {
|
||||
Add(new OpcodeCall(), xt.Name);
|
||||
} else {
|
||||
Add(new OpcodeCall(xt.Target));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "ret" opcode.
|
||||
*/
|
||||
internal void Ret()
|
||||
{
|
||||
Add(new OpcodeRet());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward unconditional jump. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void Ahead()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpUncond());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'true'. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void AheadIf()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpIf());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'false'. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void AheadIfNot()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpIfNot());
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve a previous forward jump to the current code address.
|
||||
* The top of control-flow stack is popped and must be an origin.
|
||||
*/
|
||||
internal void Then()
|
||||
{
|
||||
int x = CSPopOrig();
|
||||
code[x].ResolveJump(code.Count - x - 1);
|
||||
jumpToLast = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push the current code address on the control-flow stack as a
|
||||
* destination, to be used by an ulterior backward jump.
|
||||
*/
|
||||
internal void Begin()
|
||||
{
|
||||
CSPushDest();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward unconditional jump. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void Again()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpUncond(x - code.Count - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'true'. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void AgainIf()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpIf(x - code.Count - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'false'. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void AgainIfNot()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpIfNot(x - code.Count - 1));
|
||||
}
|
||||
}
|
||||
96
T0/WordData.cs
Normal file
96
T0/WordData.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class WordData : Word {
|
||||
|
||||
ConstData blob;
|
||||
string baseBlobName;
|
||||
int offset;
|
||||
bool ongoingResolution;
|
||||
|
||||
internal WordData(T0Comp owner, string name,
|
||||
ConstData blob, int offset)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.blob = blob;
|
||||
this.offset = offset;
|
||||
StackEffect = new SType(0, 1);
|
||||
}
|
||||
|
||||
internal WordData(T0Comp owner, string name,
|
||||
string baseBlobName, int offset)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.baseBlobName = baseBlobName;
|
||||
this.offset = offset;
|
||||
StackEffect = new SType(0, 1);
|
||||
}
|
||||
|
||||
internal override void Resolve()
|
||||
{
|
||||
if (blob != null) {
|
||||
return;
|
||||
}
|
||||
if (ongoingResolution) {
|
||||
throw new Exception(String.Format(
|
||||
"circular reference in blobs ({0})", Name));
|
||||
}
|
||||
ongoingResolution = true;
|
||||
WordData wd = TC.Lookup(baseBlobName) as WordData;
|
||||
if (wd == null) {
|
||||
throw new Exception(String.Format(
|
||||
"data word '{0}' based on non-data word '{1}'",
|
||||
Name, baseBlobName));
|
||||
}
|
||||
wd.Resolve();
|
||||
blob = wd.blob;
|
||||
offset += wd.offset;
|
||||
ongoingResolution = false;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
Resolve();
|
||||
cpu.Push(new TValue(offset, new TPointerBlob(blob)));
|
||||
}
|
||||
|
||||
internal override List<ConstData> GetDataBlocks()
|
||||
{
|
||||
Resolve();
|
||||
List<ConstData> r = new List<ConstData>();
|
||||
r.Add(blob);
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
Resolve();
|
||||
dst.Add(new CodeElementUInt(0));
|
||||
dst.Add(new CodeElementUIntInt(1, blob.Address + offset));
|
||||
dst.Add(new CodeElementUInt(0));
|
||||
}
|
||||
}
|
||||
283
T0/WordInterpreted.cs
Normal file
283
T0/WordInterpreted.cs
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* The implementation for interpreted words.
|
||||
*/
|
||||
|
||||
class WordInterpreted : Word {
|
||||
|
||||
/*
|
||||
* Get the number of local variables for this word.
|
||||
*/
|
||||
internal int NumLocals {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the sequence of opcodes for this word.
|
||||
*/
|
||||
internal Opcode[] Code {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
string[] toResolve;
|
||||
|
||||
internal WordInterpreted(T0Comp owner, string name,
|
||||
int numLocals, Opcode[] code, string[] toResolve)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.Code = code;
|
||||
this.toResolve = toResolve;
|
||||
NumLocals = numLocals;
|
||||
}
|
||||
|
||||
internal override void Resolve()
|
||||
{
|
||||
if (toResolve == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < toResolve.Length; i ++) {
|
||||
string tt = toResolve[i];
|
||||
if (tt == null) {
|
||||
continue;
|
||||
}
|
||||
Code[i].ResolveTarget(TC.Lookup(tt));
|
||||
}
|
||||
toResolve = null;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
Resolve();
|
||||
cpu.Enter(Code, NumLocals);
|
||||
}
|
||||
|
||||
internal override List<Word> GetReferences()
|
||||
{
|
||||
Resolve();
|
||||
List<Word> r = new List<Word>();
|
||||
foreach (Opcode op in Code) {
|
||||
Word w = op.GetReference(TC);
|
||||
if (w != null) {
|
||||
r.Add(w);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override List<ConstData> GetDataBlocks()
|
||||
{
|
||||
Resolve();
|
||||
List<ConstData> r = new List<ConstData>();
|
||||
foreach (Opcode op in Code) {
|
||||
ConstData cd = op.GetDataBlock(TC);
|
||||
if (cd != null) {
|
||||
r.Add(cd);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
Resolve();
|
||||
int n = Code.Length;
|
||||
CodeElement[] gcode = new CodeElement[n];
|
||||
for (int i = 0; i < n; i ++) {
|
||||
gcode[i] = Code[i].ToCodeElement();
|
||||
}
|
||||
for (int i = 0; i < n; i ++) {
|
||||
Code[i].FixUp(gcode, i);
|
||||
}
|
||||
dst.Add(new CodeElementUInt((uint)NumLocals));
|
||||
for (int i = 0; i < n; i ++) {
|
||||
dst.Add(gcode[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int flowAnalysis;
|
||||
int maxDataStack;
|
||||
int maxReturnStack;
|
||||
|
||||
bool MergeSA(int[] sa, int j, int c)
|
||||
{
|
||||
if (sa[j] == Int32.MinValue) {
|
||||
sa[j] = c;
|
||||
return true;
|
||||
} else if (sa[j] != c) {
|
||||
throw new Exception(string.Format(
|
||||
"In word '{0}', offset {1}:"
|
||||
+ " stack action mismatch ({2} / {3})",
|
||||
Name, j, sa[j], c));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void AnalyseFlow()
|
||||
{
|
||||
switch (flowAnalysis) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
return;
|
||||
default:
|
||||
throw new Exception("recursive call detected in '"
|
||||
+ Name + "'");
|
||||
}
|
||||
flowAnalysis = 2;
|
||||
int n = Code.Length;
|
||||
int[] sa = new int[n];
|
||||
for (int i = 0; i < n; i ++) {
|
||||
sa[i] = Int32.MinValue;
|
||||
}
|
||||
sa[0] = 0;
|
||||
int[] toExplore = new int[n];
|
||||
int tX = 0, tY = 0;
|
||||
int off = 0;
|
||||
|
||||
int exitSA = Int32.MinValue;
|
||||
int mds = 0;
|
||||
int mrs = 0;
|
||||
|
||||
int maxDepth = 0;
|
||||
|
||||
for (;;) {
|
||||
Opcode op = Code[off];
|
||||
bool mft = op.MayFallThrough;
|
||||
int c = sa[off];
|
||||
int a;
|
||||
if (op is OpcodeCall) {
|
||||
Word w = op.GetReference(TC);
|
||||
w.AnalyseFlow();
|
||||
SType se = w.StackEffect;
|
||||
if (!se.IsKnown) {
|
||||
throw new Exception(string.Format(
|
||||
"call from '{0}' to '{1}'"
|
||||
+ " with unknown stack effect",
|
||||
Name, w.Name));
|
||||
}
|
||||
if (se.NoExit) {
|
||||
mft = false;
|
||||
a = 0;
|
||||
} else {
|
||||
a = se.DataOut - se.DataIn;
|
||||
}
|
||||
mds = Math.Max(mds, c + w.MaxDataStack);
|
||||
mrs = Math.Max(mrs, w.MaxReturnStack);
|
||||
maxDepth = Math.Min(maxDepth, c - se.DataIn);
|
||||
} else if (op is OpcodeRet) {
|
||||
if (exitSA == Int32.MinValue) {
|
||||
exitSA = c;
|
||||
} else if (exitSA != c) {
|
||||
throw new Exception(string.Format(
|
||||
"'{0}': exit stack action"
|
||||
+ " mismatch: {1} / {2}"
|
||||
+ " (offset {3})",
|
||||
Name, exitSA, c, off));
|
||||
}
|
||||
a = 0;
|
||||
} else {
|
||||
a = op.StackAction;
|
||||
mds = Math.Max(mds, c + a);
|
||||
}
|
||||
c += a;
|
||||
maxDepth = Math.Min(maxDepth, c);
|
||||
|
||||
int j = op.JumpDisp;
|
||||
if (j != 0) {
|
||||
j += off + 1;
|
||||
toExplore[tY ++] = j;
|
||||
MergeSA(sa, j, c);
|
||||
}
|
||||
off ++;
|
||||
if (!mft || !MergeSA(sa, off, c)) {
|
||||
if (tX < tY) {
|
||||
off = toExplore[tX ++];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxDataStack = mds;
|
||||
maxReturnStack = 1 + NumLocals + mrs;
|
||||
|
||||
/*
|
||||
* TODO: see about this warning. Usage of a 'fail'
|
||||
* word (that does not exit) within a 'case..endcase'
|
||||
* structure will make an unreachable opcode. In a future
|
||||
* version we might want to automatically remove dead
|
||||
* opcodes.
|
||||
for (int i = 0; i < n; i ++) {
|
||||
if (sa[i] == Int32.MinValue) {
|
||||
Console.WriteLine("warning: word '{0}',"
|
||||
+ " offset {1}: unreachable opcode",
|
||||
Name, i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
SType computed;
|
||||
if (exitSA == Int32.MinValue) {
|
||||
computed = new SType(-maxDepth, -1);
|
||||
} else {
|
||||
computed = new SType(-maxDepth, -maxDepth + exitSA);
|
||||
}
|
||||
|
||||
if (StackEffect.IsKnown) {
|
||||
if (!computed.IsSubOf(StackEffect)) {
|
||||
throw new Exception(string.Format(
|
||||
"word '{0}':"
|
||||
+ " computed stack effect {1}"
|
||||
+ " does not match declared {2}",
|
||||
Name, computed.ToString(),
|
||||
StackEffect.ToString()));
|
||||
}
|
||||
} else {
|
||||
StackEffect = computed;
|
||||
}
|
||||
|
||||
flowAnalysis = 1;
|
||||
}
|
||||
|
||||
internal override int MaxDataStack {
|
||||
get {
|
||||
AnalyseFlow();
|
||||
return maxDataStack;
|
||||
}
|
||||
}
|
||||
|
||||
internal override int MaxReturnStack {
|
||||
get {
|
||||
AnalyseFlow();
|
||||
return maxReturnStack;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
T0/WordNative.cs
Normal file
59
T0/WordNative.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Class for native words.
|
||||
*/
|
||||
|
||||
class WordNative : Word {
|
||||
|
||||
/*
|
||||
* A type for the native implementation: a method that takes a
|
||||
* CPU as parameter, and returns nothing.
|
||||
*/
|
||||
internal delegate void NativeRun(CPU cpu);
|
||||
|
||||
NativeRun code;
|
||||
|
||||
internal WordNative(T0Comp owner, string name, NativeRun code)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
internal WordNative(T0Comp owner, string name,
|
||||
SType stackEffect, NativeRun code)
|
||||
: this(owner, name, code)
|
||||
{
|
||||
StackEffect = stackEffect;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
code(cpu);
|
||||
}
|
||||
}
|
||||
309
T0/kern.t0
Normal file
309
T0/kern.t0
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
: \ `\n parse drop ; immediate
|
||||
|
||||
\ This file defines the core non-native functions (mainly used for
|
||||
\ parsing words, i.e. not part of the generated output). The line above
|
||||
\ defines the syntax for comments.
|
||||
|
||||
\ Define parenthesis comments.
|
||||
\ : ( `) parse drop ; immediate
|
||||
|
||||
: else postpone ahead 1 cs-roll postpone then ; immediate
|
||||
: while postpone if 1 cs-roll ; immediate
|
||||
: repeat postpone again postpone then ; immediate
|
||||
|
||||
: ['] ' ; immediate
|
||||
: [compile] compile ; immediate
|
||||
|
||||
: 2drop drop drop ;
|
||||
: dup2 over over ;
|
||||
|
||||
\ Local variables are defined with the native word '(local)'. We define
|
||||
\ a helper construction that mimics what is found in Apple's Open Firmware
|
||||
\ implementation. The syntax is: { a b ... ; c d ... }
|
||||
\ I.e. there is an opening brace, then some names. Names appearing before
|
||||
\ the semicolon are locals that are both defined and then filled with the
|
||||
\ values on stack (in stack order: { a b } fills 'b' with the top-of-stack,
|
||||
\ and 'a' with the value immediately below). Names appearing after the
|
||||
\ semicolon are not initialized.
|
||||
: __deflocal ( from_stack name -- )
|
||||
dup (local) swap if
|
||||
compile-local-write
|
||||
else
|
||||
drop
|
||||
then ;
|
||||
: __deflocals ( from_stack -- )
|
||||
next-word
|
||||
dup "}" eqstr if
|
||||
2drop ret
|
||||
then
|
||||
dup ";" eqstr if
|
||||
2drop 0 __deflocals ret
|
||||
then
|
||||
over __deflocals
|
||||
__deflocal ;
|
||||
: {
|
||||
-1 __deflocals ; immediate
|
||||
|
||||
\ Data building words.
|
||||
: data:
|
||||
new-data-block next-word define-data-word ;
|
||||
: hexb|
|
||||
0 0 { acc z }
|
||||
begin
|
||||
char
|
||||
dup `| = if
|
||||
z if "Truncated hexadecimal byte" puts cr exitvm then
|
||||
ret
|
||||
then
|
||||
dup 0x20 > if
|
||||
hexval
|
||||
z if acc 4 << + data-add8 else >acc then
|
||||
z not >z
|
||||
then
|
||||
again ;
|
||||
|
||||
\ Convert hexadecimal character to number. Complain loudly if conversion
|
||||
\ is not possible.
|
||||
: hexval ( char -- x )
|
||||
hexval-nf dup 0 < if "Not an hex digit: " puts . cr exitvm then ;
|
||||
|
||||
\ Convert hexadecimal character to number. If not an hexadecimal digit,
|
||||
\ return -1.
|
||||
: hexval-nf ( char -- x )
|
||||
dup dup `0 >= swap `9 <= and if `0 - ret then
|
||||
dup dup `A >= swap `F <= and if `A - 10 + ret then
|
||||
dup dup `a >= swap `f <= and if `a - 10 + ret then
|
||||
drop -1 ;
|
||||
|
||||
\ Convert decimal character to number. Complain loudly if conversion
|
||||
\ is not possible.
|
||||
: decval ( char -- x )
|
||||
decval-nf dup 0 < if "Not a decimal digit: " puts . cr exitvm then ;
|
||||
|
||||
\ Convert decimal character to number. If not a decimal digit,
|
||||
\ return -1.
|
||||
: decval-nf ( char -- x )
|
||||
dup dup `0 >= swap `9 <= and if `0 - ret then
|
||||
drop -1 ;
|
||||
|
||||
\ Commonly used shorthands.
|
||||
: 1+ 1 + ;
|
||||
: 2+ 2 + ;
|
||||
: 1- 1 - ;
|
||||
: 2- 2 - ;
|
||||
: 0= 0 = ;
|
||||
: 0<> 0 <> ;
|
||||
: 0< 0 < ;
|
||||
: 0> 0 > ;
|
||||
|
||||
\ Get a 16-bit value from the constant data block. This uses big-endian
|
||||
\ encoding.
|
||||
: data-get16 ( addr -- x )
|
||||
dup data-get8 8 << swap 1+ data-get8 + ;
|
||||
|
||||
\ The case..endcase construction is the equivalent of 'switch' is C.
|
||||
\ Usage:
|
||||
\ case
|
||||
\ E1 of C1 endof
|
||||
\ E2 of C2 endof
|
||||
\ ...
|
||||
\ CN
|
||||
\ endcase
|
||||
\
|
||||
\ Upon entry, it considers the TOS (let's call it X). It will then evaluate
|
||||
\ E1, which should yield a single value Y1; at that point, the X value is
|
||||
\ still on the stack, just below Y1, and must remain untouched. The 'of'
|
||||
\ word compares X with Y1; if they are equal, C1 is executed, and then
|
||||
\ control jumps to after the 'endcase'. The X value is popped from the
|
||||
\ stack immediately before evaluating C1.
|
||||
\
|
||||
\ If X and Y1 are not equal, flow proceeds to E2, to obtain a value Y2 to
|
||||
\ compare with X. And so on.
|
||||
\
|
||||
\ If none of the 'of' clauses found a match, then CN is evaluated. When CN
|
||||
\ is evaluated, the X value is on the TOS, and CN must either leave it on
|
||||
\ the stack, or replace it with exactly one value; the 'endcase' word
|
||||
\ expects (and drops) one value.
|
||||
\
|
||||
\ Implementation: this is mostly copied from ANS Forth specification,
|
||||
\ although simplified a bit because we know that our control-flow stack
|
||||
\ is independent of the data stack. During compilation, the number of
|
||||
\ clauses is maintained on the stack; each of..endof clause really is
|
||||
\ an 'if..else' that must be terminated with a matching 'then' in 'endcase'.
|
||||
|
||||
: case 0 ; immediate
|
||||
: of 1+ postpone over postpone = postpone if postpone drop ; immediate
|
||||
: endof postpone else ; immediate
|
||||
: endcase
|
||||
postpone drop
|
||||
begin dup while 1- postpone then repeat drop ; immediate
|
||||
|
||||
\ A simpler and more generic "case": there is no management for a value
|
||||
\ on the stack, and each test is supposed to come up with its own boolean
|
||||
\ value.
|
||||
: choice 0 ; immediate
|
||||
: uf 1+ postpone if ; immediate
|
||||
: ufnot 1+ postpone ifnot ; immediate
|
||||
: enduf postpone else ; immediate
|
||||
: endchoice begin dup while 1- postpone then repeat drop ; immediate
|
||||
|
||||
\ C implementations for native words that can be used in generated code.
|
||||
add-cc: co { T0_CO(); }
|
||||
add-cc: execute { T0_ENTER(ip, rp, T0_POP()); }
|
||||
add-cc: drop { (void)T0_POP(); }
|
||||
add-cc: dup { T0_PUSH(T0_PEEK(0)); }
|
||||
add-cc: swap { T0_SWAP(); }
|
||||
add-cc: over { T0_PUSH(T0_PEEK(1)); }
|
||||
add-cc: rot { T0_ROT(); }
|
||||
add-cc: -rot { T0_NROT(); }
|
||||
add-cc: roll { T0_ROLL(T0_POP()); }
|
||||
add-cc: pick { T0_PICK(T0_POP()); }
|
||||
add-cc: + {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a + b);
|
||||
}
|
||||
add-cc: - {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a - b);
|
||||
}
|
||||
add-cc: neg {
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-a);
|
||||
}
|
||||
add-cc: * {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a * b);
|
||||
}
|
||||
add-cc: / {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSHi(a / b);
|
||||
}
|
||||
add-cc: u/ {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a / b);
|
||||
}
|
||||
add-cc: % {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSHi(a % b);
|
||||
}
|
||||
add-cc: u% {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a % b);
|
||||
}
|
||||
add-cc: < {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
}
|
||||
add-cc: <= {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
}
|
||||
add-cc: > {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a > b));
|
||||
}
|
||||
add-cc: >= {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
}
|
||||
add-cc: = {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a == b));
|
||||
}
|
||||
add-cc: <> {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a != b));
|
||||
}
|
||||
add-cc: u< {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
}
|
||||
add-cc: u<= {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
}
|
||||
add-cc: u> {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a > b));
|
||||
}
|
||||
add-cc: u>= {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
}
|
||||
add-cc: and {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a & b);
|
||||
}
|
||||
add-cc: or {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a | b);
|
||||
}
|
||||
add-cc: xor {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a ^ b);
|
||||
}
|
||||
add-cc: not {
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(~a);
|
||||
}
|
||||
add-cc: << {
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x << c);
|
||||
}
|
||||
add-cc: >> {
|
||||
int c = (int)T0_POPi();
|
||||
int32_t x = T0_POPi();
|
||||
T0_PUSHi(x >> c);
|
||||
}
|
||||
add-cc: u>> {
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x >> c);
|
||||
}
|
||||
add-cc: data-get8 {
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(t0_datablock[addr]);
|
||||
}
|
||||
|
||||
add-cc: . {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf(" %ld", (long)T0_POPi());
|
||||
}
|
||||
add-cc: putc {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("%c", (char)T0_POPi());
|
||||
}
|
||||
add-cc: puts {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("%s", &t0_datablock[T0_POPi()]);
|
||||
}
|
||||
add-cc: cr {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("\n");
|
||||
}
|
||||
add-cc: eqstr {
|
||||
const void *b = &t0_datablock[T0_POPi()];
|
||||
const void *a = &t0_datablock[T0_POPi()];
|
||||
T0_PUSH(-(int32_t)(strcmp(a, b) == 0));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue