mirror of https://github.com/aamine/cbc
* net/loveruby/cflat/compiler/Compiler.java: create TypeTable here.
* net/loveruby/cflat/compiler/CodeGenerator.java: accepts TypeTable and ErrorHandler. * net/loveruby/cflat/compiler/TypeResolver.java: ditto. * net/loveruby/cflat/compiler/TypeChecker.java: ditto. * net/loveruby/cflat/compiler/TypeChecker.java: set type of AddressNode. * net/loveruby/cflat/compiler/TypeChecker.java: warn incompatible cast. * net/loveruby/cflat/compiler/ErrorHandler.java: modify message (error -> warning). * net/loveruby/cflat/parser/Parser.jj: rename variable: handler -> errorHandler. * net/loveruby/cflat/ast/AST.java: do not contain TypeTable. * net/loveruby/cflat/ast/ComplexTypeDefinition.java: new method #type. * net/loveruby/cflat/ast/StructNode.java: ditto. * net/loveruby/cflat/ast/UnionNode.java: ditto. * net/loveruby/cflat/ast/AddressNode.java: receive Type from TypeChcker. * net/loveruby/cflat/type/TypeTable.java: new method #pointerTo. * net/loveruby/cflat/type/IntegerType.java (isCompatible): check if self is compatible with other side (be able to cast to other implicitly). * net/loveruby/cflat/type/IntegerType.java (isCastableTo): allow explicit cast if type of type is same (integer/pointer). * net/loveruby/cflat/type/PointerType.java: implement #equals. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@3763 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
5fc167d2e5
commit
1e4ac4dabf
47
ChangeLog
47
ChangeLog
|
@ -1,3 +1,50 @@
|
|||
Tue Jan 1 23:21:22 2008 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/Compiler.java: create TypeTable
|
||||
here.
|
||||
|
||||
* net/loveruby/cflat/compiler/CodeGenerator.java: accepts
|
||||
TypeTable and ErrorHandler.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeResolver.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeChecker.java: set type of
|
||||
AddressNode.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeChecker.java: warn incompatible
|
||||
cast.
|
||||
|
||||
* net/loveruby/cflat/compiler/ErrorHandler.java: modify message
|
||||
(error -> warning).
|
||||
|
||||
* net/loveruby/cflat/parser/Parser.jj: rename variable: handler ->
|
||||
errorHandler.
|
||||
|
||||
* net/loveruby/cflat/ast/AST.java: do not contain TypeTable.
|
||||
|
||||
* net/loveruby/cflat/ast/ComplexTypeDefinition.java: new method
|
||||
#type.
|
||||
|
||||
* net/loveruby/cflat/ast/StructNode.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/UnionNode.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/AddressNode.java: receive Type from
|
||||
TypeChcker.
|
||||
|
||||
* net/loveruby/cflat/type/TypeTable.java: new method #pointerTo.
|
||||
|
||||
* net/loveruby/cflat/type/IntegerType.java (isCompatible): check
|
||||
if self is compatible with other side (be able to cast to other
|
||||
implicitly).
|
||||
|
||||
* net/loveruby/cflat/type/IntegerType.java (isCastableTo): allow
|
||||
explicit cast if type of type is same (integer/pointer).
|
||||
|
||||
* net/loveruby/cflat/type/PointerType.java: implement #equals.
|
||||
|
||||
Tue Jan 1 21:56:19 2008 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/Compiler.java: invoke TypeChecker.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
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 {
|
||||
|
@ -9,7 +8,6 @@ public class AST extends Node {
|
|||
protected Token firstToken;
|
||||
|
||||
protected ToplevelScope scope;
|
||||
protected TypeTable typeTable;
|
||||
protected ConstantTable constantTable;
|
||||
|
||||
public AST(String fname, Declarations decls, Token t) {
|
||||
|
@ -18,7 +16,6 @@ public class AST extends Node {
|
|||
declarations = decls;
|
||||
firstToken = t;
|
||||
scope = new ToplevelScope();
|
||||
typeTable = TypeTable.ilp32(); // FIXME: platform dependent
|
||||
constantTable = new ConstantTable();
|
||||
}
|
||||
|
||||
|
@ -73,10 +70,6 @@ public class AST extends Node {
|
|||
return scope;
|
||||
}
|
||||
|
||||
public TypeTable typeTable() {
|
||||
return typeTable;
|
||||
}
|
||||
|
||||
public ConstantTable constantTable() {
|
||||
return constantTable;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class AddressNode extends UnaryOpNode {
|
||||
protected Type type;
|
||||
|
||||
public AddressNode(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
if (type == null) throw new Error("type is null");
|
||||
return type;
|
||||
}
|
||||
|
||||
/** This method is called in TypeChecker. */
|
||||
public void setType(Type type) {
|
||||
if (this.type != null) throw new Error("type set twice");
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ abstract public class ComplexTypeDefinition extends TypeDefinition {
|
|||
return true;
|
||||
}
|
||||
|
||||
abstract public String type();
|
||||
|
||||
public List members() {
|
||||
return members;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ public class StructNode extends ComplexTypeDefinition {
|
|||
super(ref, name, membs);
|
||||
}
|
||||
|
||||
public String type() {
|
||||
return "struct";
|
||||
}
|
||||
|
||||
public TypeRef typeRef() {
|
||||
return super.typeRef();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ public class UnionNode extends ComplexTypeDefinition {
|
|||
super(ref, name, membs);
|
||||
}
|
||||
|
||||
public String type() {
|
||||
return "union";
|
||||
}
|
||||
|
||||
public TypeRef typeRef() {
|
||||
return (UnionTypeRef)super.typeRef();
|
||||
}
|
||||
|
|
|
@ -5,22 +5,26 @@ import net.loveruby.cflat.asm.*;
|
|||
import java.util.*;
|
||||
|
||||
public class CodeGenerator implements ASTVisitor {
|
||||
static public String generate(AST ast) {
|
||||
return new CodeGenerator(new Assembler()).generateAssembly(ast);
|
||||
static public String generate(AST ast, TypeTable typeTable,
|
||||
ErrorHandler errorHandler) {
|
||||
CodeGenerator gen = new CodeGenerator(new Assembler(), errorHandler);
|
||||
return gen.generateAssembly(ast, typeTable);
|
||||
}
|
||||
|
||||
protected Assembler as;
|
||||
protected DefinedFunction currentFunction;
|
||||
protected TypeTable typeTable;
|
||||
protected ErrorHandler errorHandler;
|
||||
|
||||
public CodeGenerator(Assembler as) {
|
||||
public CodeGenerator(Assembler as, ErrorHandler errorHandler) {
|
||||
this.as = as;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
static public void p(String s) { System.err.println(s); }
|
||||
|
||||
/** Compiles "ast" and generates assembly code. */
|
||||
public String generateAssembly(AST ast) {
|
||||
typeTable = ast.typeTable();
|
||||
public String generateAssembly(AST ast, TypeTable typeTable) {
|
||||
typeTable = typeTable;
|
||||
allocateGlobalVariables(ast.globalVariables());
|
||||
allocateCommonSymbols(ast.commonSymbols());
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.loveruby.cflat.compiler;
|
||||
import net.loveruby.cflat.parser.*;
|
||||
import net.loveruby.cflat.ast.*;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
@ -11,17 +12,20 @@ public class Compiler {
|
|||
}
|
||||
|
||||
static final private String programId = "cbc";
|
||||
protected TypeTable typeTable;
|
||||
protected LibraryLoader loader;
|
||||
protected ErrorHandler handler;
|
||||
protected ErrorHandler errorHandler;
|
||||
|
||||
public Compiler() {
|
||||
typeTable = TypeTable.ilp32();
|
||||
loader = new LibraryLoader();
|
||||
handler = new ErrorHandler(programId);
|
||||
errorHandler = new ErrorHandler(programId);
|
||||
}
|
||||
|
||||
public Compiler(LibraryLoader ld, ErrorHandler h) {
|
||||
public Compiler(TypeTable table, LibraryLoader ld, ErrorHandler h) {
|
||||
typeTable = table;
|
||||
loader = ld;
|
||||
handler = h;
|
||||
errorHandler = h;
|
||||
}
|
||||
|
||||
public void commandMain(String[] args) {
|
||||
|
@ -54,7 +58,7 @@ public class Compiler {
|
|||
}
|
||||
|
||||
private void errorExit(String msg) {
|
||||
handler.error(msg);
|
||||
errorHandler.error(msg);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
@ -73,18 +77,19 @@ public class Compiler {
|
|||
}
|
||||
|
||||
public void compileFile(String path) throws CompileException {
|
||||
TypeTable typeTable = TypeTable.ilp32();
|
||||
AST ast = parseFile(path);
|
||||
JumpResolver.resolve(ast, handler);
|
||||
LocalReferenceResolver.resolve(ast, handler);
|
||||
TypeResolver.resolve(ast);
|
||||
TypeChecker.check(ast, handler);
|
||||
String asm = CodeGenerator.generate(ast);
|
||||
JumpResolver.resolve(ast, errorHandler);
|
||||
LocalReferenceResolver.resolve(ast, errorHandler);
|
||||
TypeResolver.resolve(ast, typeTable, errorHandler);
|
||||
TypeChecker.check(ast, typeTable, errorHandler);
|
||||
String asm = CodeGenerator.generate(ast, typeTable, errorHandler);
|
||||
writeFile(asmFileName(path), asm);
|
||||
assemble(asmFileName(path));
|
||||
}
|
||||
|
||||
public AST parseFile(String path) throws CompileException {
|
||||
return Parser.parseFile(new File(path), loader, handler);
|
||||
return Parser.parseFile(new File(path), loader, errorHandler);
|
||||
}
|
||||
|
||||
public void assemble(String path) throws IPCException {
|
||||
|
@ -97,17 +102,17 @@ public class Compiler {
|
|||
Process proc = Runtime.getRuntime().exec(cmd);
|
||||
proc.waitFor();
|
||||
if (proc.exitValue() != 0) {
|
||||
handler.error("gcc failed (assemble); status " +
|
||||
errorHandler.error("gcc failed (assemble); status " +
|
||||
proc.exitValue());
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
handler.error("gcc interrupted: " + ex.getMessage());
|
||||
errorHandler.error("gcc interrupted: " + ex.getMessage());
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
catch (IOException ex) {
|
||||
handler.error(ex.getMessage());
|
||||
errorHandler.error(ex.getMessage());
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
}
|
||||
|
@ -125,11 +130,11 @@ public class Compiler {
|
|||
}
|
||||
}
|
||||
catch (FileNotFoundException ex) {
|
||||
handler.error("file not found: " + path);
|
||||
errorHandler.error("file not found: " + path);
|
||||
throw new FileException("file error");
|
||||
}
|
||||
catch (IOException ex) {
|
||||
handler.error("IO error" + ex.getMessage());
|
||||
errorHandler.error("IO error" + ex.getMessage());
|
||||
throw new FileException("file error");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public class ErrorHandler {
|
|||
}
|
||||
|
||||
public void warn(String msg) {
|
||||
stream.println(programId + ": error: " + msg);
|
||||
stream.println(programId + ": warning: " + msg);
|
||||
nWarning++;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,16 @@ import net.loveruby.cflat.exception.*;
|
|||
import java.util.*;
|
||||
|
||||
class TypeChecker extends Visitor {
|
||||
static public void check(AST ast, ErrorHandler handler)
|
||||
throws SemanticException {
|
||||
new TypeChecker(handler).visit(ast);
|
||||
static public void check(AST ast, TypeTable typeTable,
|
||||
ErrorHandler handler) throws SemanticException {
|
||||
new TypeChecker(typeTable, handler).visit(ast);
|
||||
}
|
||||
|
||||
protected TypeTable typeTable;
|
||||
protected ErrorHandler handler;
|
||||
|
||||
public TypeChecker(ErrorHandler handler) {
|
||||
public TypeChecker(TypeTable typeTable, ErrorHandler handler) {
|
||||
this.typeTable = typeTable;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
|
@ -272,6 +274,7 @@ class TypeChecker extends Visitor {
|
|||
super.visit(node);
|
||||
// FIXME: check types
|
||||
// FIXME: check if callable
|
||||
// FIXME: check argument types
|
||||
}
|
||||
|
||||
public void visit(ArefNode node) {
|
||||
|
@ -297,6 +300,8 @@ class TypeChecker extends Visitor {
|
|||
|
||||
public void visit(AddressNode node) {
|
||||
super.visit(node);
|
||||
Type t = typeTable.pointerTo(node.expr().type());
|
||||
node.setType(t);
|
||||
// FIXME: what is "assignable"??
|
||||
}
|
||||
|
||||
|
@ -305,6 +310,11 @@ class TypeChecker extends Visitor {
|
|||
if (! node.expr().type().isCastableTo(node.type())) {
|
||||
incompatibleTypeError(node.expr().type(), node.type());
|
||||
}
|
||||
else if (! node.expr().type().isCompatible(node.type())) {
|
||||
handler.warn("incompatible cast from " +
|
||||
node.expr().type().textize() +
|
||||
" to " + node.type().textize());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -4,15 +4,20 @@ import net.loveruby.cflat.type.*;
|
|||
import java.util.*;
|
||||
|
||||
public class TypeResolver extends Visitor implements DefinitionVisitor {
|
||||
static public void resolve(AST ast) {
|
||||
new TypeResolver().resolveProgram(ast);
|
||||
static public void resolve(AST ast, TypeTable typeTable,
|
||||
ErrorHandler errorHandler) {
|
||||
new TypeResolver(typeTable, errorHandler).resolveProgram(ast);
|
||||
}
|
||||
|
||||
protected TypeTable typeTable;
|
||||
protected ErrorHandler errorHandler;
|
||||
|
||||
public TypeResolver(TypeTable typeTable, ErrorHandler errorHandler) {
|
||||
this.typeTable = typeTable;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public void resolveProgram(AST ast) {
|
||||
typeTable = ast.typeTable();
|
||||
//importLibraries(ast.importLibraryNames());
|
||||
defineTypes(ast.types());
|
||||
resolveDeclarations(ast.types());
|
||||
resolveDeclarations(ast.declarations());
|
||||
|
@ -48,7 +53,7 @@ public class TypeResolver extends Visitor implements DefinitionVisitor {
|
|||
public void resolveComplexType(ComplexTypeDefinition def) {
|
||||
ComplexType ct = (ComplexType)typeTable.get(def.typeNode().typeRef());
|
||||
if (ct == null) {
|
||||
throw new Error("FATAL: cannot intern Struct/Union");
|
||||
throw new Error("cannot intern struct/union: " + def.name());
|
||||
}
|
||||
Iterator membs = ct.members();
|
||||
while (membs.hasNext()) {
|
||||
|
|
|
@ -15,24 +15,21 @@ import java.util.*;
|
|||
import java.io.*;
|
||||
|
||||
public class Parser {
|
||||
static public AST parseFile(File file,
|
||||
LibraryLoader loader, ErrorHandler handler)
|
||||
throws CompileException {
|
||||
return newFileParser(file, loader, handler).parse();
|
||||
static public AST parseFile(File file, LibraryLoader loader,
|
||||
ErrorHandler errorHandler) throws CompileException {
|
||||
return newFileParser(file, loader, errorHandler).parse();
|
||||
}
|
||||
|
||||
static public Declarations parseDeclFile(File file,
|
||||
LibraryLoader loader, ErrorHandler handler)
|
||||
throws CompileException {
|
||||
return newFileParser(file, loader, handler).parseDecls();
|
||||
static public Declarations parseDeclFile(File file, LibraryLoader loader,
|
||||
ErrorHandler errorHandler) throws CompileException {
|
||||
return newFileParser(file, loader, errorHandler).parseDecls();
|
||||
}
|
||||
|
||||
static public Parser newFileParser(File file,
|
||||
LibraryLoader loader, ErrorHandler handler)
|
||||
throws FileException {
|
||||
static public Parser newFileParser(File file, LibraryLoader loader,
|
||||
ErrorHandler errorHandler) throws FileException {
|
||||
try {
|
||||
return new Parser(newReader(new FileInputStream(file)),
|
||||
file.getPath(), loader, handler);
|
||||
file.getPath(), loader, errorHandler);
|
||||
}
|
||||
catch (FileNotFoundException ex) {
|
||||
throw new FileException(ex.getMessage());
|
||||
|
@ -54,14 +51,14 @@ public class Parser {
|
|||
protected LabelPool labelPool;
|
||||
protected Set knownTypedefs;
|
||||
protected LibraryLoader loader;
|
||||
protected ErrorHandler handler;
|
||||
protected ErrorHandler errorHandler;
|
||||
|
||||
public Parser(Reader s, String name,
|
||||
LibraryLoader loader, ErrorHandler handler) {
|
||||
LibraryLoader loader, ErrorHandler errorHandler) {
|
||||
this(s);
|
||||
this.sourceName = name;
|
||||
this.loader = loader;
|
||||
this.handler = handler;
|
||||
this.errorHandler = errorHandler;
|
||||
this.labelPool = new LabelPool();
|
||||
this.knownTypedefs = new HashSet();
|
||||
}
|
||||
|
@ -71,11 +68,11 @@ public class Parser {
|
|||
return compilation_unit();
|
||||
}
|
||||
catch (TokenMgrError err) {
|
||||
handler.error(err.getMessage());
|
||||
errorHandler.error(err.getMessage());
|
||||
throw new SyntaxException(err.getMessage());
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
handler.error(ex.getMessage());
|
||||
errorHandler.error(ex.getMessage());
|
||||
throw new SyntaxException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -85,11 +82,11 @@ public class Parser {
|
|||
return declaration_file();
|
||||
}
|
||||
catch (TokenMgrError ex) {
|
||||
handler.error(ex.getMessage());
|
||||
errorHandler.error(ex.getMessage());
|
||||
throw new SyntaxException(ex.getMessage());
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
handler.error(ex.getMessage());
|
||||
errorHandler.error(ex.getMessage());
|
||||
throw new SyntaxException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +329,7 @@ Declarations import_stmts():
|
|||
(libid=import_stmt()
|
||||
{
|
||||
try {
|
||||
Declarations decls = loader.loadLibrary(libid, handler);
|
||||
Declarations decls = loader.loadLibrary(libid, errorHandler);
|
||||
if (decls != null) {
|
||||
impdecls.add(decls);
|
||||
Iterator types = decls.typedefs().iterator();
|
||||
|
@ -343,7 +340,7 @@ Declarations import_stmts():
|
|||
}
|
||||
}
|
||||
catch (CompileException ex) {
|
||||
handler.error(ex.getMessage());
|
||||
errorHandler.error(ex.getMessage());
|
||||
throw new ParseException("compile error");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,10 @@ public class IntegerType extends Type {
|
|||
}
|
||||
|
||||
public boolean isCompatible(Type other) {
|
||||
return (other.isInteger() && other.size() <= size);
|
||||
return (other.isInteger() && size <= other.size());
|
||||
}
|
||||
|
||||
public boolean isCastableTo(Type target) {
|
||||
return (target.isInteger() && target.size() >= size)
|
||||
|| (target.isPointer() && target.size() >= size);
|
||||
return (target.isInteger() || target.isPointer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,12 @@ public class PointerType extends Type {
|
|||
|
||||
//public boolean isArray() { return true; }
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (! (other instanceof PointerType)) return false;
|
||||
PointerType otherptr = (PointerType)other;
|
||||
return this.base.equals(otherptr.base());
|
||||
}
|
||||
|
||||
public String textize() {
|
||||
return base.textize() + "*";
|
||||
}
|
||||
|
|
|
@ -130,6 +130,10 @@ public class TypeTable {
|
|||
table.put(ref, new UserType(ref.name(), real));
|
||||
}
|
||||
|
||||
public PointerType pointerTo(Type base) {
|
||||
return new PointerType(pointerSize, base);
|
||||
}
|
||||
|
||||
public void semanticCheck() {
|
||||
Iterator types = table.values().iterator();
|
||||
while (types.hasNext()) {
|
||||
|
|
Loading…
Reference in New Issue