From 1e4ac4dabf1d3daba3b419faa958545ba5f2fda7 Mon Sep 17 00:00:00 2001 From: Minero Aoki Date: Tue, 1 Jan 2008 14:21:26 +0000 Subject: [PATCH] * 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 --- ChangeLog | 47 +++++++++++++++++++ net/loveruby/cflat/ast/AST.java | 7 --- net/loveruby/cflat/ast/AddressNode.java | 14 ++++++ .../cflat/ast/ComplexTypeDefinition.java | 2 + net/loveruby/cflat/ast/StructNode.java | 4 ++ net/loveruby/cflat/ast/UnionNode.java | 4 ++ .../cflat/compiler/CodeGenerator.java | 14 ++++-- net/loveruby/cflat/compiler/Compiler.java | 37 ++++++++------- net/loveruby/cflat/compiler/ErrorHandler.java | 2 +- net/loveruby/cflat/compiler/TypeChecker.java | 18 +++++-- net/loveruby/cflat/compiler/TypeResolver.java | 15 ++++-- net/loveruby/cflat/parser/Parser.jj | 39 +++++++-------- net/loveruby/cflat/type/IntegerType.java | 5 +- net/loveruby/cflat/type/PointerType.java | 6 +++ net/loveruby/cflat/type/TypeTable.java | 4 ++ 15 files changed, 156 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 255dbc6..5439c07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,50 @@ +Tue Jan 1 23:21:22 2008 Minero Aoki + + * 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 * net/loveruby/cflat/compiler/Compiler.java: invoke TypeChecker. diff --git a/net/loveruby/cflat/ast/AST.java b/net/loveruby/cflat/ast/AST.java index 9b9daac..1945ea6 100644 --- a/net/loveruby/cflat/ast/AST.java +++ b/net/loveruby/cflat/ast/AST.java @@ -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; } diff --git a/net/loveruby/cflat/ast/AddressNode.java b/net/loveruby/cflat/ast/AddressNode.java index 28062c6..bc7b29e 100644 --- a/net/loveruby/cflat/ast/AddressNode.java +++ b/net/loveruby/cflat/ast/AddressNode.java @@ -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); } diff --git a/net/loveruby/cflat/ast/ComplexTypeDefinition.java b/net/loveruby/cflat/ast/ComplexTypeDefinition.java index 27d61c6..15da10d 100644 --- a/net/loveruby/cflat/ast/ComplexTypeDefinition.java +++ b/net/loveruby/cflat/ast/ComplexTypeDefinition.java @@ -16,6 +16,8 @@ abstract public class ComplexTypeDefinition extends TypeDefinition { return true; } + abstract public String type(); + public List members() { return members; } diff --git a/net/loveruby/cflat/ast/StructNode.java b/net/loveruby/cflat/ast/StructNode.java index eaff89c..e205a69 100644 --- a/net/loveruby/cflat/ast/StructNode.java +++ b/net/loveruby/cflat/ast/StructNode.java @@ -7,6 +7,10 @@ public class StructNode extends ComplexTypeDefinition { super(ref, name, membs); } + public String type() { + return "struct"; + } + public TypeRef typeRef() { return super.typeRef(); } diff --git a/net/loveruby/cflat/ast/UnionNode.java b/net/loveruby/cflat/ast/UnionNode.java index ab51251..7fe2a80 100644 --- a/net/loveruby/cflat/ast/UnionNode.java +++ b/net/loveruby/cflat/ast/UnionNode.java @@ -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(); } diff --git a/net/loveruby/cflat/compiler/CodeGenerator.java b/net/loveruby/cflat/compiler/CodeGenerator.java index 3ca428e..6918373 100644 --- a/net/loveruby/cflat/compiler/CodeGenerator.java +++ b/net/loveruby/cflat/compiler/CodeGenerator.java @@ -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()); diff --git a/net/loveruby/cflat/compiler/Compiler.java b/net/loveruby/cflat/compiler/Compiler.java index 55f6909..7e2a875 100644 --- a/net/loveruby/cflat/compiler/Compiler.java +++ b/net/loveruby/cflat/compiler/Compiler.java @@ -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"); } } diff --git a/net/loveruby/cflat/compiler/ErrorHandler.java b/net/loveruby/cflat/compiler/ErrorHandler.java index 89f4218..8d2e240 100644 --- a/net/loveruby/cflat/compiler/ErrorHandler.java +++ b/net/loveruby/cflat/compiler/ErrorHandler.java @@ -23,7 +23,7 @@ public class ErrorHandler { } public void warn(String msg) { - stream.println(programId + ": error: " + msg); + stream.println(programId + ": warning: " + msg); nWarning++; } diff --git a/net/loveruby/cflat/compiler/TypeChecker.java b/net/loveruby/cflat/compiler/TypeChecker.java index 68c4a81..3c7b9d2 100644 --- a/net/loveruby/cflat/compiler/TypeChecker.java +++ b/net/loveruby/cflat/compiler/TypeChecker.java @@ -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()); + } } // diff --git a/net/loveruby/cflat/compiler/TypeResolver.java b/net/loveruby/cflat/compiler/TypeResolver.java index 7111446..75654a2 100644 --- a/net/loveruby/cflat/compiler/TypeResolver.java +++ b/net/loveruby/cflat/compiler/TypeResolver.java @@ -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()) { diff --git a/net/loveruby/cflat/parser/Parser.jj b/net/loveruby/cflat/parser/Parser.jj index 1319fe8..a3b2002 100644 --- a/net/loveruby/cflat/parser/Parser.jj +++ b/net/loveruby/cflat/parser/Parser.jj @@ -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"); } } diff --git a/net/loveruby/cflat/type/IntegerType.java b/net/loveruby/cflat/type/IntegerType.java index f340d4e..21aa858 100644 --- a/net/loveruby/cflat/type/IntegerType.java +++ b/net/loveruby/cflat/type/IntegerType.java @@ -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()); } } diff --git a/net/loveruby/cflat/type/PointerType.java b/net/loveruby/cflat/type/PointerType.java index d74bb87..7f95aee 100644 --- a/net/loveruby/cflat/type/PointerType.java +++ b/net/loveruby/cflat/type/PointerType.java @@ -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() + "*"; } diff --git a/net/loveruby/cflat/type/TypeTable.java b/net/loveruby/cflat/type/TypeTable.java index 6050f22..8541e37 100644 --- a/net/loveruby/cflat/type/TypeTable.java +++ b/net/loveruby/cflat/type/TypeTable.java @@ -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()) {