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:
Minero Aoki 2007-12-24 08:19:51 +00:00
parent 23905e35fb
commit dd209e191b
272 changed files with 11008 additions and 0 deletions

1536
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

72
README Normal file
View File

@ -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>.

191
ToDo Normal file
View File

@ -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

10
build.properties Normal file
View File

@ -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

10
build.properties.mbp Normal file
View File

@ -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

28
build.xml Normal file
View File

@ -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>

View File

@ -0,0 +1,4 @@
package net.loveruby.cflat.asm;
abstract public class Address extends AsmEntity {
}

View File

@ -0,0 +1,6 @@
package net.loveruby.cflat.asm;
abstract public class AsmEntity {
abstract public String toString();
abstract public AsmEntity add(long n);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,6 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.asm.Label;
public interface BreakableStmt {
public Label endLabel();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,6 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.asm.Label;
public interface ContinueableStmt {
public Label continueLabel();
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,7 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.asm.*;
public interface LHSNode {
public boolean isConstantAddress();
public AsmEntity address();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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