mirror of https://github.com/aamine/cbc
import cbc from stdcompiler repository (rev185)
git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@3753 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
23905e35fb
commit
dd209e191b
|
|
@ -0,0 +1,72 @@
|
|||
CbC - Cflat Compiler
|
||||
====================
|
||||
|
||||
This is the CbC, Cflat programming language compiler.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
To compile cbc itself:
|
||||
|
||||
* Java SDK 1.4 or later
|
||||
* JavaCC 4.0 or later
|
||||
|
||||
To run cbc and compiled program:
|
||||
|
||||
* Linux 2.4 or later
|
||||
* GNU libc 2.3 or later
|
||||
* GNU binutils (as, ld)
|
||||
* util-linux (ld-linux.so.2)
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
# sudo ./install.sh
|
||||
|
||||
or
|
||||
|
||||
$ prefix=$HOME/local ./install.sh
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Modified BSD license.
|
||||
For details of modified BSD license, see following:
|
||||
|
||||
Copyright (c) 2007,2007 Minero Aoki. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of the Minero Aoki nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY MINERO AOKI ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
CbC produced by Minero Aoki <aamine@loveruby.net>.
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
- generate resolved AST
|
||||
- constant table
|
||||
- types
|
||||
- scope, frame
|
||||
- integer literal
|
||||
- 1, 2, 3, ...
|
||||
- octal (010)
|
||||
- hex (0x1f)
|
||||
- 1U, 1L, 1UL
|
||||
- character literal
|
||||
- 'c'
|
||||
- standard escape sequence ('\n', ...)
|
||||
- octal escape sequence ('\077')
|
||||
- string literal
|
||||
- "string"
|
||||
- standard escape sequence ('\n', ...)
|
||||
- octal escape sequence ("\077")
|
||||
- import
|
||||
- single import
|
||||
- recursive import
|
||||
- import function
|
||||
- import type
|
||||
- build x86 test environment
|
||||
- compile "Hello, World"
|
||||
- write unit tests
|
||||
- funcall
|
||||
- 0 arg
|
||||
- 1 arg
|
||||
- 2 args
|
||||
- 3
|
||||
- 4 - 10 args
|
||||
- variables
|
||||
- param
|
||||
- reference
|
||||
- assign
|
||||
- lvar
|
||||
- assign
|
||||
- reference
|
||||
- initializer
|
||||
- common symbol
|
||||
- assign
|
||||
- reference
|
||||
- global variable
|
||||
- define
|
||||
- reference
|
||||
- assign
|
||||
- private common symbol
|
||||
- assign
|
||||
- reference
|
||||
- private global variable
|
||||
- define
|
||||
- assign
|
||||
- reference
|
||||
- function-static variable
|
||||
- assign
|
||||
- reference
|
||||
- initializer
|
||||
- op
|
||||
- +
|
||||
- -
|
||||
- *
|
||||
- /
|
||||
- %
|
||||
- bitwise op
|
||||
- ~
|
||||
- &
|
||||
- |
|
||||
- ^
|
||||
- >>
|
||||
- <<
|
||||
- unary op
|
||||
- +@
|
||||
- -@
|
||||
- !
|
||||
- comparison op
|
||||
- ==
|
||||
- !=
|
||||
- >
|
||||
- >=
|
||||
- <
|
||||
- <=
|
||||
- self assignment
|
||||
- +=, -=, *=, ...
|
||||
- ++
|
||||
- --
|
||||
- control structure
|
||||
- if
|
||||
- while
|
||||
- flow
|
||||
- break
|
||||
- continue
|
||||
- for
|
||||
- flow
|
||||
- break
|
||||
- continue
|
||||
- do...while
|
||||
- flow
|
||||
- break
|
||||
- continue
|
||||
- switch
|
||||
- goto
|
||||
- valued control structure
|
||||
- &&
|
||||
- ||
|
||||
- a ? b : c
|
||||
- array
|
||||
- as LHS
|
||||
- as RHS
|
||||
- reject negative length array definition
|
||||
- struct
|
||||
- as LHS
|
||||
- as RHS
|
||||
- recursive definition with pointer
|
||||
- union
|
||||
- as LHS
|
||||
- as RHS
|
||||
- recursive definition with pointer
|
||||
* composite literal {1,2,3...}
|
||||
- parse (initializer)
|
||||
- parse (rhs)
|
||||
* type check
|
||||
* code generation
|
||||
- pointer
|
||||
- *ptr
|
||||
- *ptr = val
|
||||
- ptr->memb
|
||||
- ptr->memb = val
|
||||
- &expr
|
||||
- as RHS
|
||||
* ?? as LHS
|
||||
- function pointer
|
||||
- refer
|
||||
- call ptr(arg)
|
||||
* complex LHS
|
||||
- local variable
|
||||
* parameter
|
||||
* global variables / common symbols
|
||||
* static variables
|
||||
* *arr[0] = ...
|
||||
* *st.memb = ...
|
||||
* *ptr++ = ...
|
||||
* *(ptr + N) = ...
|
||||
* *(int*)ptr = ...
|
||||
* their combination
|
||||
- bare block ({...})
|
||||
- cast
|
||||
- semantic check (control)
|
||||
- reject break from out of loop/switch
|
||||
- reject continue from out of loop
|
||||
- semantic check (reference)
|
||||
- check all symbols are resolved
|
||||
- check duplicated parameters
|
||||
- check if the calling function exists
|
||||
- warn unused static variables
|
||||
- warn unused local variables
|
||||
- warn unused static functions
|
||||
* semantic check (type)
|
||||
- prohibit circular struct/union definition
|
||||
* type check
|
||||
* implicit cast
|
||||
* check duplicated struct/union members
|
||||
* check if struct member is valid
|
||||
* check if union member is valid
|
||||
- op for various types
|
||||
- signed char
|
||||
- signed short
|
||||
- signed int
|
||||
- signed long
|
||||
- unsigned char
|
||||
- unsigned short
|
||||
- unsigned int
|
||||
- unsigned long
|
||||
- Multibyte input
|
||||
* parse command line option
|
||||
* --dump-tokens
|
||||
* --dump-ast
|
||||
* ?? --dump-semantic
|
||||
* generate IR
|
||||
* --dump-ir
|
||||
* control flow graph
|
||||
* --dump-cflow
|
||||
* semantic check (cflow)
|
||||
* warn unreachable stmt
|
||||
* warn no return
|
||||
* data flow graph
|
||||
* --dump-dflow
|
||||
* warn uninitialized use of variables
|
||||
* semantic check (dflow)
|
||||
* register allocation
|
||||
* vararg retrieve
|
||||
* 64bit long_long support
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
javacc.dir=/usr/share/java
|
||||
|
||||
src.dir=.
|
||||
build.dir=build
|
||||
build.classes.dir=build/classes
|
||||
|
||||
src.jjt.file=${src.dir}/net/loveruby/cflat/parser/Parser.jjt
|
||||
build.parser.dir=${src.dir}/net/loveruby/cflat/parser
|
||||
build.jj.file=${build.parser.dir}/Parser.jj
|
||||
src.jj.file=${src.dir}/net/loveruby/cflat/parser/Parser.jj
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
javacc.dir=/opt/local/share/java
|
||||
|
||||
src.dir=.
|
||||
build.dir=build
|
||||
build.classes.dir=build/classes
|
||||
|
||||
src.jjt.file=${src.dir}/net/loveruby/cflat/parser/Parser.jjt
|
||||
build.parser.dir=${src.dir}/net/loveruby/cflat/parser
|
||||
build.jj.file=${build.parser.dir}/Parser.jj
|
||||
src.jj.file=${src.dir}/net/loveruby/cflat/parser/Parser.jj
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="CflatCompiler" default="compile" basedir=".">
|
||||
<target name="init">
|
||||
<property file="build.properties" />
|
||||
</target>
|
||||
<target name="parser" depends="init">
|
||||
<javacc target="${src.jj.file}"
|
||||
javacchome="${javacc.dir}" />
|
||||
</target>
|
||||
<target name="compile" depends="init, parser">
|
||||
<mkdir dir="${build.dir}" />
|
||||
<mkdir dir="${build.classes.dir}" />
|
||||
<javac destdir="${build.classes.dir}" srcdir="${src.dir}"
|
||||
debug="true" source="1.4">
|
||||
<include name="net/**/*.java" />
|
||||
</javac>
|
||||
</target>
|
||||
<target name="clean" depends="init">
|
||||
<delete dir="${build.dir}" />
|
||||
<delete file="${build.parser.dir}/Parser.java" />
|
||||
<delete file="${build.parser.dir}/ParserConstants.java" />
|
||||
<delete file="${build.parser.dir}/ParserTokenManager.java" />
|
||||
<delete file="${build.parser.dir}/ParseException.java" />
|
||||
<delete file="${build.parser.dir}/Token.java" />
|
||||
<delete file="${build.parser.dir}/TokenMgrError.java" />
|
||||
<delete file="${build.parser.dir}/SimpleCharStream.java" />
|
||||
</target>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
abstract public class Address extends AsmEntity {
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
abstract public class AsmEntity {
|
||||
abstract public String toString();
|
||||
abstract public AsmEntity add(long n);
|
||||
}
|
||||
|
|
@ -0,0 +1,358 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Assembler {
|
||||
List list;
|
||||
|
||||
public Assembler() {
|
||||
list = new ArrayList();
|
||||
}
|
||||
|
||||
public String string() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Iterator i = list.iterator();
|
||||
while (i.hasNext()) {
|
||||
buf.append((String)i.next());
|
||||
buf.append("\n");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
protected void op(String op) {
|
||||
list.add("\t" + op);
|
||||
}
|
||||
|
||||
protected void op(String op, AsmEntity ent) {
|
||||
list.add("\t" + op + "\t" + ent.toString());
|
||||
}
|
||||
|
||||
protected void op(String op, AsmEntity ent1, AsmEntity ent2) {
|
||||
list.add("\t" + op + "\t" + ent1.toString() + ", " + ent2.toString());
|
||||
}
|
||||
|
||||
protected void op(String op, String arg) {
|
||||
list.add("\t" + op + "\t" + arg);
|
||||
}
|
||||
|
||||
protected void op(String op, String arg1, String arg2) {
|
||||
list.add("\t" + op + "\t" + arg1 + ", " + arg2);
|
||||
}
|
||||
|
||||
protected void op(String op, String arg1, String arg2, String arg3) {
|
||||
list.add("\t" + op + "\t" + arg1 + ", " + arg2 + ", " + arg3);
|
||||
}
|
||||
|
||||
public void line(String str) {
|
||||
list.add(str);
|
||||
}
|
||||
|
||||
public void _file(String name) {
|
||||
line("\t.file\t" + escapeString(name));
|
||||
}
|
||||
|
||||
public void _text() {
|
||||
line("\t.text");
|
||||
}
|
||||
|
||||
public void _data() {
|
||||
line("\t.data");
|
||||
}
|
||||
|
||||
public void _section(String name) {
|
||||
line("\t.section\t" + name);
|
||||
}
|
||||
|
||||
public void _globl(String sym) {
|
||||
line(".globl " + sym);
|
||||
}
|
||||
|
||||
public void _local(String sym) {
|
||||
line(".local " + sym);
|
||||
}
|
||||
|
||||
public void _comm(String sym, long size, long alignment) {
|
||||
line("\t.comm\t" + sym + "," + size + "," + alignment);
|
||||
}
|
||||
|
||||
public void _align(long n) {
|
||||
line("\t.align\t" + n);
|
||||
}
|
||||
|
||||
public void _type(String sym, String type) {
|
||||
line("\t.type\t" + sym + ", " + type);
|
||||
}
|
||||
|
||||
public void _size(String sym, long size) {
|
||||
_size(sym, new Long(size).toString());
|
||||
}
|
||||
|
||||
public void _size(String sym, String size) {
|
||||
line("\t.size\t" + sym + ", " + size);
|
||||
}
|
||||
|
||||
public void _byte(long n) {
|
||||
line(".byte\t" + n);
|
||||
}
|
||||
|
||||
public void _value(long n) {
|
||||
line(".value\t" + n);
|
||||
}
|
||||
|
||||
public void _long(long n) {
|
||||
line(".long\t" + n);
|
||||
}
|
||||
|
||||
public void _quad(long n) {
|
||||
line(".quad\t" + n);
|
||||
}
|
||||
|
||||
public void _string(String str) {
|
||||
line("\t.string\t" + escapeString(str));
|
||||
}
|
||||
|
||||
static final char bell = 007;
|
||||
static final char vtab = 013;
|
||||
|
||||
protected String escapeString(String str) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("\"");
|
||||
for (int n = 0; n < str.length(); n++) {
|
||||
char c = str.charAt(n);
|
||||
if (c == '"') buf.append("\\\"");
|
||||
else if (isPrintable(c)) buf.append(c);
|
||||
else if (c == '\0') buf.append("\\000");
|
||||
else if (c == bell) buf.append("\\007");
|
||||
else if (c == '\b') buf.append("\\b");
|
||||
else if (c == '\t') buf.append("\\t");
|
||||
else if (c == '\n') buf.append("\\n");
|
||||
else if (c == vtab) buf.append("\\v");
|
||||
else if (c == '\f') buf.append("\\f");
|
||||
else if (c == '\r') buf.append("\\r");
|
||||
else {
|
||||
buf.append("\\" + Integer.toOctalString((int)c));
|
||||
}
|
||||
}
|
||||
buf.append("\"");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
protected boolean isPrintable(char c) {
|
||||
return (' ' <= c) && (c <= '~');
|
||||
}
|
||||
|
||||
public void label(String label) {
|
||||
line(label + ":");
|
||||
}
|
||||
|
||||
public void label(Label label) {
|
||||
line(label.toString() + ":");
|
||||
}
|
||||
|
||||
public void jmp(Label label) {
|
||||
op("jmp", label);
|
||||
}
|
||||
|
||||
public void jz(Label label) {
|
||||
op("jz", label);
|
||||
}
|
||||
|
||||
public void jnz(Label label) {
|
||||
op("jnz", label);
|
||||
}
|
||||
|
||||
public void je(Label label) {
|
||||
op("je", label);
|
||||
}
|
||||
|
||||
public void jne(Label label) {
|
||||
op("jne", label);
|
||||
}
|
||||
|
||||
protected void typedOp(Type t, String op, AsmEntity a) {
|
||||
op(addSuffix(op, t), a);
|
||||
}
|
||||
|
||||
protected void typedOp(Type t, String op, AsmEntity a, AsmEntity b) {
|
||||
op(addSuffix(op, t), a, b);
|
||||
}
|
||||
|
||||
protected String addSuffix(String op, Type t) {
|
||||
switch ((int)t.size()) {
|
||||
case 1: return op + "b";
|
||||
case 2: return op + "w";
|
||||
case 4: return op + "l";
|
||||
case 8: return op + "q";
|
||||
default:
|
||||
throw new Error("unknown type size: " + t.size());
|
||||
}
|
||||
}
|
||||
|
||||
public void cmp(Type t, Register a, Register b) {
|
||||
typedOp(t, "cmp", a, b);
|
||||
}
|
||||
|
||||
public void sete(Register reg) {
|
||||
op("sete", reg);
|
||||
}
|
||||
|
||||
public void setne(Register reg) {
|
||||
op("setne", reg);
|
||||
}
|
||||
|
||||
public void setg(Register reg) {
|
||||
op("setg", reg);
|
||||
}
|
||||
|
||||
public void setl(Register reg) {
|
||||
op("setl", reg);
|
||||
}
|
||||
|
||||
public void setge(Register reg) {
|
||||
op("setge", reg);
|
||||
}
|
||||
|
||||
public void setle(Register reg) {
|
||||
op("setle", reg);
|
||||
}
|
||||
|
||||
public void test(Type type, Register a, Register b) {
|
||||
typedOp(type, "test", a, b);
|
||||
}
|
||||
|
||||
public void pushq(Register reg) {
|
||||
op("pushl", reg);
|
||||
}
|
||||
|
||||
public void popq(Register reg) {
|
||||
op("popl", reg);
|
||||
}
|
||||
|
||||
public void call(String sym) {
|
||||
op("call", sym);
|
||||
}
|
||||
|
||||
public void ptrcall(Register reg) {
|
||||
op("call", "*" + reg.toString());
|
||||
}
|
||||
|
||||
public void ret() {
|
||||
op("ret");
|
||||
}
|
||||
|
||||
public void movq(AsmEntity src, AsmEntity dest) {
|
||||
op("movl", src, dest);
|
||||
}
|
||||
|
||||
public void mov(Type type, AsmEntity src, AsmEntity dest) {
|
||||
typedOp(type, "mov", src, dest);
|
||||
}
|
||||
|
||||
public void movsbl(AsmEntity src, AsmEntity dest) {
|
||||
op("movsbl", src, dest);
|
||||
}
|
||||
|
||||
public void movswl(AsmEntity src, AsmEntity dest) {
|
||||
op("movswl", src, dest);
|
||||
}
|
||||
|
||||
public void movzb(Type type, AsmEntity src, AsmEntity dest) {
|
||||
typedOp(type, "movzb", src, dest);
|
||||
}
|
||||
|
||||
public void movzbl(AsmEntity src, AsmEntity dest) {
|
||||
op("movzbl", src, dest);
|
||||
}
|
||||
|
||||
public void movzwl(AsmEntity src, AsmEntity dest) {
|
||||
op("movzwl", src, dest);
|
||||
}
|
||||
|
||||
public void leaq(AsmEntity src, AsmEntity dest) {
|
||||
op("leal", src, dest);
|
||||
}
|
||||
|
||||
public void lea(Type type, AsmEntity src, AsmEntity dest) {
|
||||
typedOp(type, "lea", src, dest);
|
||||
}
|
||||
|
||||
public void neg(Type type, Register reg) {
|
||||
typedOp(type, "neg", reg);
|
||||
}
|
||||
|
||||
public void inc(Type type, AsmEntity reg) {
|
||||
typedOp(type, "inc", reg);
|
||||
}
|
||||
|
||||
public void dec(Type type, AsmEntity reg) {
|
||||
typedOp(type, "dec", reg);
|
||||
}
|
||||
|
||||
public void addq(AsmEntity diff, Register base) {
|
||||
op("addl", diff, base);
|
||||
}
|
||||
|
||||
public void add(Type type, AsmEntity diff, Register base) {
|
||||
typedOp(type, "add", diff, base);
|
||||
}
|
||||
|
||||
public void subq(AsmEntity diff, Register base) {
|
||||
op("subl", diff, base);
|
||||
}
|
||||
|
||||
public void sub(Type type, Register diff, Register base) {
|
||||
typedOp(type, "sub", diff, base);
|
||||
}
|
||||
|
||||
public void imulq(AsmEntity m, Register base) {
|
||||
op("imull", m, base);
|
||||
}
|
||||
|
||||
public void imul(Type type, AsmEntity m, Register base) {
|
||||
typedOp(type, "imul", m, base);
|
||||
}
|
||||
|
||||
public void idiv(Type type, Register base) {
|
||||
typedOp(type, "idiv", base);
|
||||
}
|
||||
|
||||
public void not(Type type, Register reg) {
|
||||
typedOp(type, "not", reg);
|
||||
}
|
||||
|
||||
public void and(Type type, Register bits, Register base) {
|
||||
typedOp(type, "and", bits, base);
|
||||
}
|
||||
|
||||
public void or(Type type, Register bits, Register base) {
|
||||
typedOp(type, "or", bits, base);
|
||||
}
|
||||
|
||||
public void xor(Type type, Register bits, Register base) {
|
||||
typedOp(type, "xor", bits, base);
|
||||
}
|
||||
|
||||
public void sar(Type type, Register bits, Register base) {
|
||||
typedOp(type, "sar", bits, base);
|
||||
}
|
||||
|
||||
public void sal(Type type, Register bits, Register base) {
|
||||
typedOp(type, "sal", bits, base);
|
||||
}
|
||||
|
||||
public void shr(Type type, Register bits, Register base) {
|
||||
typedOp(type, "shr", bits, base);
|
||||
}
|
||||
|
||||
public void shl(Type type, Register bits, Register base) {
|
||||
typedOp(type, "shl", bits, base);
|
||||
}
|
||||
|
||||
public void rol(Type type, Register bits, Register base) {
|
||||
typedOp(type, "rol", bits, base);
|
||||
}
|
||||
|
||||
public void ror(Type type, Register bits, Register base) {
|
||||
typedOp(type, "ror", bits, base);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
public class CompositeAddress extends Address {
|
||||
long offset;
|
||||
Register base;
|
||||
|
||||
public CompositeAddress(long off, Register reg) {
|
||||
offset = off;
|
||||
base = reg;
|
||||
}
|
||||
|
||||
public long offset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public Register base() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "" + offset + "(" + base.toString() + ")";
|
||||
}
|
||||
|
||||
public AsmEntity add(long n) {
|
||||
return new CompositeAddress(offset + n, base);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
public class ImmediateValue extends AsmEntity {
|
||||
long value;
|
||||
|
||||
public ImmediateValue(long n) {
|
||||
value = n;
|
||||
}
|
||||
|
||||
public long value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "$" + value;
|
||||
}
|
||||
|
||||
public AsmEntity add(long n) {
|
||||
return new ImmediateValue(value + n);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
public class Label extends AsmEntity {
|
||||
long seq;
|
||||
String name;
|
||||
|
||||
public Label(String n) {
|
||||
seq = -1;
|
||||
name = n;
|
||||
}
|
||||
|
||||
public Label(long s, String n) {
|
||||
seq = s;
|
||||
name = n;
|
||||
}
|
||||
|
||||
public long seq() {
|
||||
return seq;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public AsmEntity add(long offset) {
|
||||
throw new Error("Label#add"); // FIXME
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
public class LabelPool {
|
||||
long seq;
|
||||
|
||||
public LabelPool() {
|
||||
seq = 0;
|
||||
}
|
||||
|
||||
public Label newLabel() {
|
||||
seq++;
|
||||
return new Label(seq, ".L" + seq);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
public class Reference extends Address {
|
||||
protected Label label;
|
||||
|
||||
public Reference(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public AsmEntity add(long n) {
|
||||
// FIXME??
|
||||
// MemberNode#address calls this method.
|
||||
// Some combination does not allows this optimization,
|
||||
// caller should validate operation before call.
|
||||
// Or, throw specific exception and catch it.
|
||||
throw new Error("Reference#add");
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "$" + label.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class Register extends AsmEntity {
|
||||
static public Register forType(Type t, String name) {
|
||||
switch ((int)t.size()) {
|
||||
case 1: return new Register(name);
|
||||
case 2: return new Register(name);
|
||||
case 4: return new Register("e" + name);
|
||||
case 8: return new Register("r" + name);
|
||||
default:
|
||||
throw new Error("invalid register size: " + t.size());
|
||||
}
|
||||
}
|
||||
|
||||
static public Register widestRegister(String name) {
|
||||
return new Register("e" + name);
|
||||
}
|
||||
|
||||
String name;
|
||||
|
||||
public Register(String n) {
|
||||
name = n;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "%" + name;
|
||||
}
|
||||
|
||||
public AsmEntity add(long n) {
|
||||
return new CompositeAddress(n, this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package net.loveruby.cflat.asm;
|
||||
|
||||
public class SimpleAddress extends Address {
|
||||
Register base;
|
||||
|
||||
public SimpleAddress(Register reg) {
|
||||
base = reg;
|
||||
}
|
||||
|
||||
public Register base() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "(" + base.toString() + ")";
|
||||
}
|
||||
|
||||
public AsmEntity add(long n) {
|
||||
return new CompositeAddress(n, base);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.parser.Token;
|
||||
import net.loveruby.cflat.type.TypeTable;
|
||||
import java.util.*;
|
||||
|
||||
public class AST extends Node {
|
||||
protected String fileName;
|
||||
protected Declarations declarations;
|
||||
protected Token firstToken;
|
||||
|
||||
protected ToplevelScope scope;
|
||||
protected TypeTable typeTable;
|
||||
protected ConstantTable constantTable;
|
||||
|
||||
public AST(String fname, Declarations decls, Token t) {
|
||||
super();
|
||||
fileName = fname;
|
||||
declarations = decls;
|
||||
firstToken = t;
|
||||
scope = new ToplevelScope();
|
||||
typeTable = TypeTable.ilp32(); // FIXME: platform dependent
|
||||
constantTable = new ConstantTable();
|
||||
}
|
||||
|
||||
public String fileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public Iterator types() {
|
||||
List result = new ArrayList();
|
||||
result.addAll(declarations.defstructs());
|
||||
result.addAll(declarations.defunions());
|
||||
result.addAll(declarations.typedefs());
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
public Iterator entities() {
|
||||
List result = new ArrayList();
|
||||
result.addAll(declarations.defvars());
|
||||
result.addAll(declarations.defuns());
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
public Iterator globalVariables() {
|
||||
return scope.globalVariables().iterator();
|
||||
}
|
||||
|
||||
public Iterator commonSymbols() {
|
||||
return scope.commonSymbols().iterator();
|
||||
}
|
||||
|
||||
public boolean functionDefined() {
|
||||
return !declarations.defuns().isEmpty();
|
||||
}
|
||||
|
||||
public Iterator functions() {
|
||||
return declarations.defuns().iterator();
|
||||
}
|
||||
|
||||
public void declare(UndefinedFunction f) {
|
||||
declarations.funcdecls().add(f);
|
||||
}
|
||||
|
||||
public Iterator declarations() {
|
||||
List result = new ArrayList();
|
||||
//result.addAll(declarations.defvars());
|
||||
//result.addAll(declarations.defuns());
|
||||
result.addAll(declarations.funcdecls());
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
public ToplevelScope scope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public TypeTable typeTable() {
|
||||
return typeTable;
|
||||
}
|
||||
|
||||
public ConstantTable constantTable() {
|
||||
return constantTable;
|
||||
}
|
||||
|
||||
public void dump(String prefix) {
|
||||
System.out.println("FIXME: dump AST");
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
throw new Error("AST#accept");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public interface ASTVisitor {
|
||||
public void visit(BlockNode node);
|
||||
public void visit(IfNode node);
|
||||
public void visit(CondExprNode node);
|
||||
public void visit(SwitchNode node);
|
||||
public void visit(CaseNode node);
|
||||
public void visit(WhileNode node);
|
||||
public void visit(DoWhileNode node);
|
||||
public void visit(ForNode node);
|
||||
public void visit(BreakNode node);
|
||||
public void visit(ContinueNode node);
|
||||
public void visit(GotoNode node);
|
||||
public void visit(LabelNode node);
|
||||
public void visit(ReturnNode node);
|
||||
public void visit(AssignNode node);
|
||||
public void visit(PlusAssignNode node);
|
||||
public void visit(MinusAssignNode node);
|
||||
public void visit(MulAssignNode node);
|
||||
public void visit(DivAssignNode node);
|
||||
public void visit(ModAssignNode node);
|
||||
public void visit(AndAssignNode node);
|
||||
public void visit(OrAssignNode node);
|
||||
public void visit(XorAssignNode node);
|
||||
public void visit(LShiftAssignNode node);
|
||||
public void visit(RShiftAssignNode node);
|
||||
public void visit(LogicalOrNode node);
|
||||
public void visit(LogicalAndNode node);
|
||||
public void visit(GtNode node);
|
||||
public void visit(LtNode node);
|
||||
public void visit(GtEqNode node);
|
||||
public void visit(LtEqNode node);
|
||||
public void visit(EqNode node);
|
||||
public void visit(NotEqNode node);
|
||||
public void visit(BitwiseOrNode node);
|
||||
public void visit(BitwiseXorNode node);
|
||||
public void visit(BitwiseAndNode node);
|
||||
public void visit(RShiftNode node);
|
||||
public void visit(LShiftNode node);
|
||||
public void visit(PlusNode node);
|
||||
public void visit(MinusNode node);
|
||||
public void visit(MulNode node);
|
||||
public void visit(DivNode node);
|
||||
public void visit(ModNode node);
|
||||
public void visit(SuffixIncNode node);
|
||||
public void visit(SuffixDecNode node);
|
||||
public void visit(ArefNode node);
|
||||
public void visit(MemberNode node);
|
||||
public void visit(PtrMemberNode node);
|
||||
public void visit(IntegerLiteralNode node);
|
||||
public void visit(CharacterLiteralNode node);
|
||||
public void visit(StringLiteralNode node);
|
||||
public void visit(FuncallNode node);
|
||||
public void visit(VariableNode node);
|
||||
public void visit(UnaryPlusNode node);
|
||||
public void visit(UnaryMinusNode node);
|
||||
public void visit(LogicalNotNode node);
|
||||
public void visit(BitwiseNotNode node);
|
||||
public void visit(DereferenceNode node);
|
||||
public void visit(AddressNode node);
|
||||
public void visit(PrefixIncNode node);
|
||||
public void visit(PrefixDecNode node);
|
||||
public void visit(CastNode node);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
abstract public class AbstractAssignNode extends Node {
|
||||
Node lhs, rhs;
|
||||
|
||||
public AbstractAssignNode(Node l, Node r) {
|
||||
super();
|
||||
lhs = l;
|
||||
rhs = r;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return lhs.type();
|
||||
}
|
||||
|
||||
public Node lhs() {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
public Node rhs() {
|
||||
return rhs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class AddressNode extends UnaryOpNode {
|
||||
public AddressNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class AndAssignNode extends AbstractAssignNode {
|
||||
public AndAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class ArefNode extends Node implements LHSNode {
|
||||
protected Node expr, index;
|
||||
|
||||
public ArefNode(Node n, Node idx) {
|
||||
expr = n;
|
||||
index = idx;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return ((ArrayType)expr.type()).base();
|
||||
}
|
||||
|
||||
public Node expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public Node index() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
// FIXME
|
||||
return false;
|
||||
}
|
||||
|
||||
public AsmEntity address() {
|
||||
// FIXME
|
||||
throw new Error("ArefNode#address");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class AssignNode extends Node {
|
||||
Node lhs, rhs;
|
||||
|
||||
public AssignNode(Node l, Node r) {
|
||||
super();
|
||||
lhs = l;
|
||||
rhs = r;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
// invariant(lhs.type == rhs.type)
|
||||
return lhs.type();
|
||||
}
|
||||
|
||||
public Node lhs() {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
public Node rhs() {
|
||||
return rhs;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.Type;
|
||||
|
||||
abstract public class BinaryOpNode extends Node {
|
||||
protected Node left, right;
|
||||
|
||||
public BinaryOpNode(Node l, Node r) {
|
||||
super();
|
||||
left = l;
|
||||
right = r;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return left.type();
|
||||
}
|
||||
|
||||
public Node left() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public Node right() {
|
||||
return right;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class BitwiseAndNode extends BinaryOpNode {
|
||||
public BitwiseAndNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class BitwiseNotNode extends UnaryOpNode {
|
||||
public BitwiseNotNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class BitwiseOrNode extends BinaryOpNode {
|
||||
public BitwiseOrNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class BitwiseXorNode extends BinaryOpNode {
|
||||
public BitwiseXorNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import java.util.*;
|
||||
|
||||
public class BlockNode extends Node {
|
||||
protected List variables;
|
||||
protected List stmts;
|
||||
|
||||
public BlockNode(List vars, List ss) {
|
||||
variables = vars;
|
||||
stmts = ss;
|
||||
}
|
||||
|
||||
public Iterator variables() {
|
||||
return variables.iterator();
|
||||
}
|
||||
|
||||
public Iterator stmts() {
|
||||
return stmts.iterator();
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
protected Scope scope;
|
||||
|
||||
public Scope scope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(Scope s) {
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class BreakNode extends Node {
|
||||
public BreakNode() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
protected Label label;
|
||||
|
||||
public void setTargetLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Label targetLabel() {
|
||||
if (label == null) {
|
||||
throw new Error("break label is null");
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
|
||||
public interface BreakableStmt {
|
||||
public Label endLabel();
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
import java.util.*;
|
||||
|
||||
public class CaseNode extends Node {
|
||||
protected LabelPool pool;
|
||||
protected Label beginLabel;
|
||||
protected List values;
|
||||
protected BlockNode body;
|
||||
|
||||
public CaseNode(LabelPool pool, List values, BlockNode body) {
|
||||
super();
|
||||
this.pool = pool;
|
||||
this.values = values;
|
||||
this.body = body;
|
||||
this.beginLabel = null;
|
||||
}
|
||||
|
||||
public Iterator values() {
|
||||
return values.iterator();
|
||||
}
|
||||
|
||||
public BlockNode body() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public Label beginLabel() {
|
||||
if (beginLabel == null) {
|
||||
beginLabel = pool.newLabel();
|
||||
}
|
||||
return beginLabel;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class CastNode extends Node {
|
||||
protected TypeNode typeNode;
|
||||
protected Node expr;
|
||||
|
||||
public CastNode(TypeNode t, Node n) {
|
||||
typeNode = t;
|
||||
expr = n;
|
||||
}
|
||||
|
||||
public void resolve(TypeTable table) {
|
||||
System.err.println("FIXME: CastNode#resolve not implemented");
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return typeNode.type();
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public Node expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class CharacterLiteralNode extends Node {
|
||||
protected TypeNode typeNode;
|
||||
protected long value;
|
||||
|
||||
public CharacterLiteralNode(TypeRef ref, long i) {
|
||||
typeNode = new TypeNode(ref);
|
||||
value = i;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return typeNode.type();
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public long value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
abstract public class ComplexTypeDefinition extends TypeDefinition {
|
||||
protected List members;
|
||||
protected TypeNode typeNode;
|
||||
|
||||
public ComplexTypeDefinition(TypeRef ref, String name, List membs) {
|
||||
super(name);
|
||||
members = membs;
|
||||
typeNode = new TypeNode(ref);
|
||||
}
|
||||
|
||||
public boolean isComplexType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public List members() {
|
||||
return members;
|
||||
}
|
||||
|
||||
public TypeRef typeRef() {
|
||||
return typeNode.typeRef();
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
public class CompositeLiteralNode extends Node {
|
||||
protected List members;
|
||||
protected Type type;
|
||||
|
||||
public CompositeLiteralNode(List membs) {
|
||||
this.members = membs;
|
||||
}
|
||||
|
||||
public Iterator members() {
|
||||
return members.iterator();
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
if (type == null) {
|
||||
throw new Error("CompositeLiteralNode#type == null");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Type t) {
|
||||
if (type != null) {
|
||||
throw new Error("CompositeLiteralNode#setType called twice");
|
||||
}
|
||||
type = t;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
throw new Error("CompositeLiteralNode#accept called");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class CondExprNode extends IfNode {
|
||||
public CondExprNode(LabelPool lp, Node c, Node t, Node e) {
|
||||
super(lp, c, t, e);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.AsmEntity;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
|
||||
public class ConstantEntry
|
||||
{
|
||||
protected long id;
|
||||
protected String value;
|
||||
protected Label label;
|
||||
|
||||
public ConstantEntry(long i, String val) {
|
||||
id = i;
|
||||
value = val;
|
||||
label = new Label(".LC" + id);
|
||||
}
|
||||
|
||||
public long id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Label label() {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import java.util.*;
|
||||
|
||||
public class ConstantTable
|
||||
{
|
||||
protected HashMap table;
|
||||
protected long id;
|
||||
|
||||
public ConstantTable() {
|
||||
table = new HashMap();
|
||||
id = 0;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return table.isEmpty();
|
||||
}
|
||||
|
||||
public ConstantEntry intern(String s) {
|
||||
ConstantEntry ent = (ConstantEntry)table.get(s);
|
||||
if (ent == null) {
|
||||
ent = new ConstantEntry(id++, s);
|
||||
table.put(s, ent);
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
public Iterator entries() {
|
||||
return table.values().iterator();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class ContinueNode extends Node {
|
||||
public ContinueNode() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
protected Label label;
|
||||
|
||||
public void setTargetLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Label targetLabel() {
|
||||
if (label == null) {
|
||||
throw new Error("continue target label is null");
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
|
||||
public interface ContinueableStmt {
|
||||
public Label continueLabel();
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
abstract public class Declaration {
|
||||
protected String name;
|
||||
|
||||
public Declaration(String n) {
|
||||
name = n;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
abstract public void accept(DefinitionVisitor visitor);
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import java.util.*;
|
||||
|
||||
public class Declarations {
|
||||
protected List defvars, vardecls, defuns, funcdecls;
|
||||
protected List defstructs, defunions, typedefs;
|
||||
|
||||
public Declarations() {
|
||||
defvars = new ArrayList();
|
||||
vardecls = new ArrayList();
|
||||
defuns = new ArrayList();
|
||||
funcdecls = new ArrayList();
|
||||
defstructs = new ArrayList();
|
||||
defunions = new ArrayList();
|
||||
typedefs = new ArrayList();
|
||||
}
|
||||
|
||||
public void add(Declarations decls) {
|
||||
vardecls.addAll(decls.vardecls());
|
||||
funcdecls.addAll(decls.funcdecls());
|
||||
defstructs.addAll(decls.defstructs());
|
||||
defunions.addAll(decls.defunions());
|
||||
typedefs.addAll(decls.typedefs());
|
||||
}
|
||||
|
||||
public void addDefvar(DefinedVariable var) {
|
||||
defvars.add(var);
|
||||
}
|
||||
|
||||
public List defvars() {
|
||||
return defvars;
|
||||
}
|
||||
|
||||
public void addVardecl(UndefinedVariable var) {
|
||||
vardecls.add(var);
|
||||
}
|
||||
|
||||
public List vardecls() {
|
||||
return vardecls;
|
||||
}
|
||||
|
||||
public void addDefun(Function func) {
|
||||
defuns.add(func);
|
||||
}
|
||||
|
||||
public List defuns() {
|
||||
return defuns;
|
||||
}
|
||||
|
||||
public void addFuncdecl(UndefinedFunction func) {
|
||||
funcdecls.add(func);
|
||||
}
|
||||
|
||||
public List funcdecls() {
|
||||
return funcdecls;
|
||||
}
|
||||
|
||||
public void addDefstruct(StructNode n) {
|
||||
defstructs.add(n);
|
||||
}
|
||||
|
||||
public List defstructs() {
|
||||
return defstructs;
|
||||
}
|
||||
|
||||
public void addDefunion(UnionNode n) {
|
||||
defunions.add(n);
|
||||
}
|
||||
|
||||
public List defunions() {
|
||||
return defunions;
|
||||
}
|
||||
|
||||
public void addTypedef(TypedefNode n) {
|
||||
typedefs.add(n);
|
||||
}
|
||||
|
||||
public List typedefs() {
|
||||
return typedefs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.compiler.ErrorHandler;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
import java.util.*;
|
||||
|
||||
public class DefinedFunction extends Function {
|
||||
protected LabelPool labelPool;
|
||||
protected Params params;
|
||||
protected Node body;
|
||||
protected Map jumpMap;
|
||||
protected Frame frame;
|
||||
|
||||
public DefinedFunction(LabelPool pool, boolean priv, TypeNode type,
|
||||
String name, Params params, Node body) {
|
||||
super(priv, type, name);
|
||||
this.labelPool = pool;
|
||||
this.params = params;
|
||||
this.body = body;
|
||||
this.jumpMap = new HashMap();
|
||||
}
|
||||
|
||||
public Iterator parameters() {
|
||||
return params.parameters();
|
||||
}
|
||||
|
||||
public Node body() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setFrame(Frame f) {
|
||||
frame = f;
|
||||
}
|
||||
|
||||
// returns function local variables.
|
||||
// Does NOT include paramters.
|
||||
// Does NOT include static local variables.
|
||||
public Iterator localVariables() {
|
||||
return frame.allVariables();
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFunction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void defineIn(ToplevelScope toplevel) {
|
||||
toplevel.defineFunction(this);
|
||||
}
|
||||
|
||||
class JumpEntry {
|
||||
public Label label;
|
||||
public long numRefered;
|
||||
public boolean isDefined;
|
||||
|
||||
public JumpEntry(Label label) {
|
||||
this.label = label;
|
||||
numRefered = 0;
|
||||
isDefined = false;
|
||||
}
|
||||
}
|
||||
|
||||
public Label defineLabel(String name) throws SemanticException {
|
||||
JumpEntry ent = getJumpEntry(name);
|
||||
if (ent.isDefined) {
|
||||
throw new SemanticException(
|
||||
"duplicated jump labels in " + name + "(): " + name);
|
||||
}
|
||||
ent.isDefined = true;
|
||||
return ent.label;
|
||||
}
|
||||
|
||||
public Label referLabel(String name) {
|
||||
JumpEntry ent = getJumpEntry(name);
|
||||
ent.numRefered++;
|
||||
return ent.label;
|
||||
}
|
||||
|
||||
protected JumpEntry getJumpEntry(String name) {
|
||||
JumpEntry ent = (JumpEntry)jumpMap.get(name);
|
||||
if (ent == null) {
|
||||
ent = new JumpEntry(labelPool.newLabel());
|
||||
jumpMap.put(name, ent);
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
public void checkJumpLinks(ErrorHandler handler) {
|
||||
Iterator ents = jumpMap.entrySet().iterator();
|
||||
while (ents.hasNext()) {
|
||||
Map.Entry ent = (Map.Entry)ents.next();
|
||||
String labelName = (String)ent.getKey();
|
||||
JumpEntry jump = (JumpEntry)ent.getValue();
|
||||
if (!jump.isDefined) {
|
||||
handler.error("undefined label in function " +
|
||||
name + ": " + labelName);
|
||||
}
|
||||
if (jump.numRefered == 0) {
|
||||
handler.warn("useless label: " + labelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void accept(DefinitionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public AsmEntity address() {
|
||||
throw new Error("must not happen: Function#address called");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class DefinedVariable extends Variable {
|
||||
protected Node initializer;
|
||||
protected AsmEntity address;
|
||||
|
||||
public DefinedVariable(boolean priv, TypeNode type,
|
||||
String name, Node init) {
|
||||
super(priv, type, name);
|
||||
initializer = init;
|
||||
toplevel = false;
|
||||
sequence = -1;
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return (initializer != null);
|
||||
}
|
||||
|
||||
public Node initializer() {
|
||||
return initializer;
|
||||
}
|
||||
|
||||
public void defineIn(ToplevelScope toplevel) {
|
||||
if (isPrivate()) {
|
||||
toplevel.allocatePrivateVariable(this);
|
||||
} else {
|
||||
toplevel.allocateVariable(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void accept(DefinitionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
abstract public class Definition extends Declaration {
|
||||
public Definition(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public boolean isEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isVariable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFunction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isComplexType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStruct() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUnion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUserType() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public interface DefinitionVisitor {
|
||||
public void visit(DefinedVariable var);
|
||||
public void visit(UndefinedVariable var);
|
||||
public void visit(DefinedFunction func);
|
||||
public void visit(UndefinedFunction func);
|
||||
public void visit(StructNode struct);
|
||||
public void visit(UnionNode union);
|
||||
public void visit(TypedefNode typedef);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class DereferenceNode extends UnaryOpNode implements LHSNode {
|
||||
public DereferenceNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public AsmEntity address() {
|
||||
throw new Error("DereferenceNode#address");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class DivAssignNode extends AbstractAssignNode {
|
||||
public DivAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class DivNode extends BinaryOpNode {
|
||||
public DivNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class DoWhileNode extends LoopNode {
|
||||
protected Node cond, body;
|
||||
|
||||
public DoWhileNode(LabelPool pool, Node b, Node c) {
|
||||
super(pool);
|
||||
body = b;
|
||||
cond = c;
|
||||
}
|
||||
|
||||
public Node body() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public Node cond() {
|
||||
return cond;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
protected Label continueLabel;
|
||||
|
||||
public Label continueLabel() {
|
||||
if (continueLabel == null) {
|
||||
continueLabel = pool.newLabel();
|
||||
}
|
||||
return continueLabel;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
abstract public class Entity extends Definition {
|
||||
protected boolean isPrivate;
|
||||
protected TypeNode typeNode;
|
||||
protected long nRefered;
|
||||
|
||||
public Entity(boolean priv, TypeNode t, String name) {
|
||||
super(name);
|
||||
isPrivate = priv;
|
||||
typeNode = t;
|
||||
}
|
||||
|
||||
public boolean isEntity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract public boolean isDefined();
|
||||
abstract public boolean isInitialized();
|
||||
|
||||
public boolean isPrivate() {
|
||||
return isPrivate;
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return typeNode.type();
|
||||
}
|
||||
|
||||
public long size() {
|
||||
return type().size();
|
||||
}
|
||||
|
||||
public long alignment() {
|
||||
return 4; // FIXME: platform dependent
|
||||
}
|
||||
|
||||
public void refered() {
|
||||
nRefered++;
|
||||
}
|
||||
|
||||
public boolean isRefered() {
|
||||
return (nRefered > 0);
|
||||
}
|
||||
|
||||
abstract public void defineIn(ToplevelScope toplevel);
|
||||
abstract public AsmEntity address();
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class EqNode extends BinaryOpNode {
|
||||
public EqNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
public class FixedParams extends Params {
|
||||
protected List parameters;
|
||||
|
||||
public FixedParams(List params) {
|
||||
parameters = params;
|
||||
}
|
||||
|
||||
public Iterator parameters() {
|
||||
return parameters.iterator();
|
||||
}
|
||||
|
||||
protected List parametersList() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public boolean isVararg() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof FixedParams)) return false;
|
||||
FixedParams params = (FixedParams)other;
|
||||
return parameters.equals(params.parametersList());
|
||||
}
|
||||
|
||||
public Params internTypes(TypeTable table) {
|
||||
Iterator it = parameters.iterator();
|
||||
List types = new ArrayList();
|
||||
while (it.hasNext()) {
|
||||
types.add(table.get((TypeRef)it.next()));
|
||||
}
|
||||
return new FixedParams(types);
|
||||
}
|
||||
|
||||
public Params typeRefs() {
|
||||
Iterator it = parameters.iterator();
|
||||
List typerefs = new ArrayList();
|
||||
while (it.hasNext()) {
|
||||
Parameter param = (Parameter)it.next();
|
||||
typerefs.add(param.typeNode().typeRef());
|
||||
}
|
||||
return new FixedParams(typerefs);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class ForNode extends LoopNode {
|
||||
protected Node init, cond, incr, body;
|
||||
|
||||
public ForNode(LabelPool pool, Node ini, Node c, Node inc, Node b) {
|
||||
super(pool);
|
||||
init = ini;
|
||||
cond = c;
|
||||
incr = inc;
|
||||
body = b;
|
||||
}
|
||||
|
||||
public Node init() {
|
||||
return init;
|
||||
}
|
||||
|
||||
public Node cond() {
|
||||
return cond;
|
||||
}
|
||||
|
||||
public Node incr() {
|
||||
return incr;
|
||||
}
|
||||
|
||||
public Node body() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
protected Label continueLabel;
|
||||
|
||||
public Label continueLabel() {
|
||||
if (continueLabel == null) {
|
||||
continueLabel = pool.newLabel();
|
||||
}
|
||||
return continueLabel;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import java.util.*;
|
||||
|
||||
public class Frame extends Scope {
|
||||
public Frame(ToplevelScope up) {
|
||||
super(up);
|
||||
}
|
||||
|
||||
public void allocatePrivateVariable(Variable var) {
|
||||
throw new Error("Frame#allocatePrivateVariable called");
|
||||
}
|
||||
|
||||
public long numLocalVariables() {
|
||||
return bodyScope().numAllEntities();
|
||||
}
|
||||
|
||||
public Iterator localVariables() {
|
||||
return bodyScope().entities();
|
||||
}
|
||||
|
||||
private Scope bodyScope() {
|
||||
return (Scope)children.get(0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
public class FuncallNode extends Node {
|
||||
protected Node expr;
|
||||
protected List args;
|
||||
|
||||
public FuncallNode(Node expr, List args) {
|
||||
this.expr = expr;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Node expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public boolean isStaticCall() {
|
||||
return (expr instanceof VariableNode) &&
|
||||
(((VariableNode)expr).entity() instanceof Function);
|
||||
}
|
||||
|
||||
public Function function() {
|
||||
return (Function)((VariableNode)expr).entity();
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return function().type();
|
||||
}
|
||||
|
||||
public long numArgs() {
|
||||
return args.size();
|
||||
}
|
||||
|
||||
public Iterator args() {
|
||||
return args.iterator();
|
||||
}
|
||||
|
||||
public ListIterator finalArg() {
|
||||
return args.listIterator(args.size());
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
import java.util.*;
|
||||
|
||||
abstract public class Function extends Entity {
|
||||
public Function(boolean priv, TypeNode t, String name) {
|
||||
super(priv, t, name);
|
||||
}
|
||||
|
||||
public boolean isFunction() { return true; }
|
||||
public boolean isInitialized() { return true; }
|
||||
abstract public boolean isDefined();
|
||||
abstract public Iterator parameters();
|
||||
abstract public AsmEntity address();
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
|
||||
public class GotoNode extends Node {
|
||||
protected String target;
|
||||
protected Label label;
|
||||
|
||||
public GotoNode(String target) {
|
||||
super();
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public String target() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public void setTargetLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Label targetLabel() {
|
||||
if (label == null) throw new Error("goto target label is null");
|
||||
return label;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class GtEqNode extends BinaryOpNode {
|
||||
public GtEqNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class GtNode extends BinaryOpNode {
|
||||
public GtNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class IfNode extends Node {
|
||||
protected Node cond, thenBody, elseBody;
|
||||
protected LabelPool pool;
|
||||
protected Label elseLabel, endLabel;
|
||||
|
||||
public IfNode(LabelPool lp, Node c, Node t, Node e) {
|
||||
super();
|
||||
pool = lp;
|
||||
cond = c;
|
||||
thenBody = t;
|
||||
elseBody = e;
|
||||
}
|
||||
|
||||
public Node cond() {
|
||||
return cond;
|
||||
}
|
||||
|
||||
public Node thenBody() {
|
||||
return thenBody;
|
||||
}
|
||||
|
||||
public Node elseBody() {
|
||||
return elseBody;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public Label elseLabel() {
|
||||
if (elseLabel == null) {
|
||||
elseLabel = pool.newLabel();
|
||||
}
|
||||
return elseLabel;
|
||||
}
|
||||
|
||||
public Label endLabel() {
|
||||
if (endLabel == null) {
|
||||
endLabel = pool.newLabel();
|
||||
}
|
||||
return endLabel;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class IntegerLiteralNode extends Node {
|
||||
protected TypeNode typeNode;
|
||||
protected long value;
|
||||
|
||||
public IntegerLiteralNode(TypeRef ref, long i) {
|
||||
typeNode = new TypeNode(ref);
|
||||
value = i;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return typeNode.type();
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public long value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public interface LHSNode {
|
||||
public boolean isConstantAddress();
|
||||
public AsmEntity address();
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class LShiftAssignNode extends AbstractAssignNode {
|
||||
public LShiftAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class LShiftNode extends BinaryOpNode {
|
||||
public LShiftNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
|
||||
public class LabelNode extends Node {
|
||||
protected String name;
|
||||
protected Node stmt;
|
||||
protected Label label;
|
||||
|
||||
public LabelNode(String name, Node stmt) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.stmt = stmt;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Node stmt() {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
public void setLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Label label() {
|
||||
if (label == null) throw new Error("label is null");
|
||||
return label;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class LogicalAndNode extends BinaryOpNode {
|
||||
protected LabelPool pool;
|
||||
protected Label endLabel;
|
||||
|
||||
public LogicalAndNode(LabelPool lp, Node left, Node right) {
|
||||
super(left, right);
|
||||
pool = lp;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public Label endLabel() {
|
||||
if (endLabel == null) {
|
||||
endLabel = pool.newLabel();
|
||||
}
|
||||
return endLabel;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class LogicalNotNode extends Node {
|
||||
Node expr;
|
||||
|
||||
public LogicalNotNode(Node n) {
|
||||
super();
|
||||
expr = n;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return expr.type();
|
||||
}
|
||||
|
||||
public Node expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class LogicalOrNode extends BinaryOpNode {
|
||||
protected LabelPool pool;
|
||||
protected Label endLabel;
|
||||
|
||||
public LogicalOrNode(LabelPool lp, Node left, Node right) {
|
||||
super(left, right);
|
||||
pool = lp;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public Label endLabel() {
|
||||
if (endLabel == null) {
|
||||
endLabel = pool.newLabel();
|
||||
}
|
||||
return endLabel;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
abstract public class LoopNode extends Node
|
||||
implements BreakableStmt, ContinueableStmt {
|
||||
protected LabelPool pool;
|
||||
protected Label begLabel, endLabel;
|
||||
|
||||
public LoopNode(LabelPool lp) {
|
||||
super();
|
||||
pool = lp;
|
||||
}
|
||||
|
||||
public Label begLabel() {
|
||||
if (begLabel == null) {
|
||||
begLabel = pool.newLabel();
|
||||
}
|
||||
return begLabel;
|
||||
}
|
||||
|
||||
public Label endLabel() {
|
||||
if (endLabel == null) {
|
||||
endLabel = pool.newLabel();
|
||||
}
|
||||
return endLabel;
|
||||
}
|
||||
|
||||
abstract public Label continueLabel();
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class LtEqNode extends BinaryOpNode {
|
||||
public LtEqNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class LtNode extends BinaryOpNode {
|
||||
public LtNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.AsmEntity;
|
||||
|
||||
public class MemberNode extends Node implements LHSNode {
|
||||
protected Node expr;
|
||||
protected String name;
|
||||
|
||||
public MemberNode(Node expr, String name) {
|
||||
this.expr = expr;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return baseType().memberType(name);
|
||||
}
|
||||
|
||||
public ComplexType baseType() {
|
||||
return (ComplexType)expr.type();
|
||||
}
|
||||
|
||||
public Node expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public long offset() {
|
||||
return baseType().memberOffset(name);
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
return ((LHSNode)expr).isConstantAddress();
|
||||
}
|
||||
|
||||
public AsmEntity address() {
|
||||
return expr.address().add(offset());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class MinusAssignNode extends AbstractAssignNode {
|
||||
public MinusAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class MinusNode extends BinaryOpNode {
|
||||
public MinusNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class ModAssignNode extends AbstractAssignNode {
|
||||
public ModAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class ModNode extends BinaryOpNode {
|
||||
public ModNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class MulAssignNode extends AbstractAssignNode {
|
||||
public MulAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class MulNode extends BinaryOpNode {
|
||||
public MulNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.Type;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
abstract public class Node {
|
||||
public Node() {
|
||||
}
|
||||
|
||||
abstract public void accept(ASTVisitor visitor);
|
||||
|
||||
public Type type() {
|
||||
throw new Error("Node#type called");
|
||||
}
|
||||
|
||||
public AsmEntity address() {
|
||||
throw new Error("Node#address");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class NotEqNode extends BinaryOpNode {
|
||||
public NotEqNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class OrAssignNode extends AbstractAssignNode {
|
||||
public OrAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class Parameter extends DefinedVariable {
|
||||
public Parameter(TypeNode type, String name) {
|
||||
super(false, type, name, null);
|
||||
}
|
||||
|
||||
public boolean isParameter() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.TypeTable;
|
||||
import java.util.*;
|
||||
|
||||
abstract public class Params extends Node {
|
||||
public void accept(ASTVisitor visitor) {
|
||||
throw new Error("do not use Params#accept");
|
||||
}
|
||||
|
||||
abstract public Iterator parameters();
|
||||
abstract public boolean isVararg();
|
||||
abstract public boolean equals(Object other);
|
||||
abstract public Params internTypes(TypeTable table);
|
||||
abstract public Params typeRefs();
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class PlusAssignNode extends AbstractAssignNode {
|
||||
public PlusAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class PlusNode extends BinaryOpNode {
|
||||
public PlusNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class PrefixDecNode extends UnaryOpNode {
|
||||
public PrefixDecNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class PrefixIncNode extends UnaryOpNode {
|
||||
public PrefixIncNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class PtrMemberNode extends Node implements LHSNode {
|
||||
public Node expr;
|
||||
public String name;
|
||||
|
||||
public PtrMemberNode(Node n, String nm) {
|
||||
expr = n;
|
||||
name = nm;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return baseType().memberType(name);
|
||||
}
|
||||
|
||||
public ComplexType baseType() {
|
||||
PointerType ptr = (PointerType)expr.type();
|
||||
return (ComplexType)ptr.base();
|
||||
}
|
||||
|
||||
public Node expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public AsmEntity address() {
|
||||
throw new Error("PtrMemberNode#address");
|
||||
}
|
||||
|
||||
public long offset() {
|
||||
return baseType().memberOffset(name);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class RShiftAssignNode extends AbstractAssignNode {
|
||||
public RShiftAssignNode(Node lhs, Node rhs) {
|
||||
super(lhs, rhs);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class RShiftNode extends BinaryOpNode {
|
||||
public RShiftNode(Node left, Node right) {
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class ReturnNode extends Node {
|
||||
Node expr;
|
||||
|
||||
public ReturnNode(Node e) {
|
||||
super();
|
||||
expr = e;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
public Node expr() {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.compiler.ErrorHandler;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Scope {
|
||||
protected Scope parent;
|
||||
protected List children;
|
||||
|
||||
protected long numAllEntities;
|
||||
protected List entities;
|
||||
protected Map entitiesMap;
|
||||
protected Map privateEntitiesMap;
|
||||
|
||||
public Scope(Scope up) {
|
||||
parent = up;
|
||||
if (up != null) up.addChild(this);
|
||||
children = new ArrayList();
|
||||
numAllEntities = -1;
|
||||
entities = new ArrayList();
|
||||
entitiesMap = new HashMap();
|
||||
privateEntitiesMap = new HashMap();
|
||||
}
|
||||
|
||||
public boolean isToplevel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ToplevelScope toplevel() {
|
||||
Scope s = this;
|
||||
while (!s.isToplevel()) {
|
||||
s = s.parent;
|
||||
}
|
||||
return (ToplevelScope)s;
|
||||
}
|
||||
|
||||
// Returns parent scope.
|
||||
// If this scope is a TopScope, parent() returns null.
|
||||
public Scope parent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
protected void addChild(Scope s) {
|
||||
children.add(s);
|
||||
}
|
||||
|
||||
// Returns a list of all child scopes.
|
||||
// Does NOT include myself.
|
||||
protected Iterator allChildren() {
|
||||
List result = new ArrayList();
|
||||
collectChildren(result);
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
protected void collectChildren(List buf) {
|
||||
Iterator cs = children.iterator();
|
||||
while (cs.hasNext()) {
|
||||
Scope c = (Scope)cs.next();
|
||||
buf.add(c);
|
||||
c.collectChildren(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/** Allocates variable var in this scope. */
|
||||
public void allocateVariable(Variable var) {
|
||||
checkDuplicatedVariable(var.name());
|
||||
addEntity(var);
|
||||
}
|
||||
|
||||
/** Allocates static variable var in this scope.
|
||||
* This method causes var defined in the top scope,
|
||||
* instead of this scope.
|
||||
*/
|
||||
public void allocateStaticLocalVariable(Variable var) {
|
||||
checkDuplicatedVariable(var.name());
|
||||
toplevel().allocateStaticLocalVariable(var);
|
||||
addPrivateEntity(var);
|
||||
}
|
||||
|
||||
protected void addEntity(Entity ent) {
|
||||
entities.add(ent);
|
||||
entitiesMap.put(ent.name(), ent);
|
||||
}
|
||||
|
||||
protected void addPrivateEntity(Entity ent) {
|
||||
privateEntitiesMap.put(ent.name(), ent);
|
||||
}
|
||||
|
||||
protected void checkDuplicatedVariable(String name) {
|
||||
if (entitiesMap.containsKey(name)
|
||||
|| privateEntitiesMap.containsKey(name)) {
|
||||
throw new Error("duplicated variable: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDefinedLocally(String name) {
|
||||
return (entitiesMap.containsKey(name)
|
||||
|| privateEntitiesMap.containsKey(name));
|
||||
}
|
||||
|
||||
public Entity get(String name) throws SemanticException {
|
||||
Entity ent;
|
||||
ent = (Entity)(privateEntitiesMap.get(name));
|
||||
if (ent != null) return ent;
|
||||
ent = (Entity)(entitiesMap.get(name));
|
||||
if (ent != null) return ent;
|
||||
return parent.get(name);
|
||||
}
|
||||
|
||||
// Returns all function local variables defined in this scope.
|
||||
// Does includes all nested local variables.
|
||||
// Does NOT include static local variables.
|
||||
public Iterator allVariables() {
|
||||
return allEntities().iterator();
|
||||
}
|
||||
|
||||
public Iterator variables() {
|
||||
return entities();
|
||||
}
|
||||
|
||||
public long numEntities() {
|
||||
return entities.size();
|
||||
}
|
||||
|
||||
// Returns local variables defined in this scope itself.
|
||||
// Does NOT include nested local variables.
|
||||
// Does NOT include static local variables.
|
||||
public Iterator entities() {
|
||||
return entities.iterator();
|
||||
}
|
||||
|
||||
public long numAllEntities() {
|
||||
if (numAllEntities < 0) {
|
||||
Iterator cs = allChildren();
|
||||
long n = 0;
|
||||
while (cs.hasNext()) {
|
||||
Scope c = (Scope)cs.next();
|
||||
n += c.numEntities();
|
||||
}
|
||||
numAllEntities = n;
|
||||
}
|
||||
return numAllEntities;
|
||||
}
|
||||
|
||||
protected List allEntities() {
|
||||
List result = new ArrayList();
|
||||
Iterator cs = allChildren();
|
||||
while (cs.hasNext()) {
|
||||
Scope c = (Scope)cs.next();
|
||||
result.addAll(c.entities);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void checkReferences(ErrorHandler handler) {
|
||||
Iterator ents = entities.iterator();
|
||||
while (ents.hasNext()) {
|
||||
Entity ent = (Entity)ents.next();
|
||||
if (ent.isDefined() && ent.isPrivate() && !ent.isRefered()) {
|
||||
handler.warn("unused variable: " + ent.name());
|
||||
}
|
||||
}
|
||||
Iterator cs = children.iterator();
|
||||
while (cs.hasNext()) {
|
||||
Scope s = (Scope)cs.next();
|
||||
s.checkReferences(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class Slot {
|
||||
protected TypeNode typeNode;
|
||||
protected String name;
|
||||
protected long offset;
|
||||
|
||||
public Slot(TypeNode t, String n) {
|
||||
typeNode = t;
|
||||
name = n;
|
||||
offset = Type.sizeUnknown;
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public TypeRef typeRef() {
|
||||
return typeNode.typeRef();
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return typeNode.type();
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long size() {
|
||||
return type().size();
|
||||
}
|
||||
|
||||
public long offset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public void setOffset(long offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
|
||||
public class StringLiteralNode extends Node {
|
||||
protected TypeNode typeNode;
|
||||
protected String value;
|
||||
protected ConstantEntry entry;
|
||||
|
||||
public StringLiteralNode(TypeRef ref, String s) {
|
||||
typeNode = new TypeNode(ref);
|
||||
value = s;
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return typeNode.type();
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setEntry(ConstantEntry ent) {
|
||||
entry = ent;
|
||||
}
|
||||
|
||||
public Label label() {
|
||||
checkEntry();
|
||||
return entry.label();
|
||||
}
|
||||
|
||||
protected long id() {
|
||||
checkEntry();
|
||||
return entry.id();
|
||||
}
|
||||
|
||||
protected void checkEntry() {
|
||||
if (entry == null)
|
||||
throw new Error("StringLiteralNode#entry not resolved");
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
public class StructNode extends ComplexTypeDefinition {
|
||||
public StructNode(TypeRef ref, String name, List membs) {
|
||||
super(ref, name, membs);
|
||||
}
|
||||
|
||||
public TypeRef typeRef() {
|
||||
return super.typeRef();
|
||||
}
|
||||
|
||||
public boolean isStruct() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void defineIn(TypeTable table) {
|
||||
table.defineStruct((StructTypeRef)typeRef(), members());
|
||||
}
|
||||
|
||||
public void accept(DefinitionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class SuffixDecNode extends UnaryOpNode {
|
||||
public SuffixDecNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
|
||||
public class SuffixIncNode extends UnaryOpNode {
|
||||
public SuffixIncNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
import java.util.*;
|
||||
|
||||
public class SwitchNode extends Node implements BreakableStmt {
|
||||
protected LabelPool pool;
|
||||
protected Node cond;
|
||||
protected List cases;
|
||||
protected Label endLabel;
|
||||
|
||||
public SwitchNode(LabelPool pool, Node cond, List cases) {
|
||||
super();
|
||||
this.pool = pool;
|
||||
this.cond = cond;
|
||||
this.cases = cases;
|
||||
}
|
||||
|
||||
public Node cond() {
|
||||
return cond;
|
||||
}
|
||||
|
||||
public Iterator cases() {
|
||||
return cases.iterator();
|
||||
}
|
||||
|
||||
public Label endLabel() {
|
||||
if (endLabel == null) {
|
||||
endLabel = pool.newLabel();
|
||||
}
|
||||
return endLabel;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue