mirror of https://github.com/aamine/cbc
r4865@macbookpro: aamine | 2009-05-18 03:02:28 +0900
* net/loveruby/cflat/parser/Parser.jj: change function pointer syntax: int(*)(int,int) -> int(int,int)*. Function type is int(int,int). * net/loveruby/cflat/parser/Parser.jj: function returns function type, not pointer to function. * net/loveruby/cflat/compiler/TypeResolver.java: resolve all function headers first, then resolve bodies. * net/loveruby/cflat/compiler/TypeResolver.java: generate a pointer for array-type expression. * net/loveruby/cflat/compiler/TypeResolver.java: isDereferable -> isPointer. * net/loveruby/cflat/compiler/TypeChecker.java: ditto. * net/loveruby/cflat/compiler/DereferenceChecker.java: ditto. * net/loveruby/cflat/compiler/IRGenerator.java: ditto. * net/loveruby/cflat/compiler/IRGenerator.java: shouldEvaluatedToAddress -> isLoadable (check arrays and functions, not only arrays). * net/loveruby/cflat/type/Type.java: remove #isDereferable. * net/loveruby/cflat/type/UserType.java: ditto. * net/loveruby/cflat/type/ArrayType.java: is not a scalar. * net/loveruby/cflat/type/ArrayType.java: is not dereferable itself. * net/loveruby/cflat/type/PointerType.java: is incompatible with arrays. * net/loveruby/cflat/type/IntegerType.java: ditto. * net/loveruby/cflat/type/FunctionType.java: is callable. * net/loveruby/cflat/type/ParamTypeRefs.java: x[] -> x* for param types. * net/loveruby/cflat/type/TypeTable.java: new method #getParamType. * net/loveruby/cflat/ast/ExprNode.java: new method #isLvalue. * net/loveruby/cflat/ast/ExprNode.java: new method #isAssignable. * net/loveruby/cflat/ast/ExprNode.java: new method #isLoadable. * net/loveruby/cflat/ast/CastNode.java: delegate them. * net/loveruby/cflat/ast/LHSNode.java: new super class of LHS nodes. * net/loveruby/cflat/ast/VariableNode.java: ditto. * net/loveruby/cflat/ast/DereferenceNode.java: ditto. * net/loveruby/cflat/ast/ArefNode.java: ditto. * net/loveruby/cflat/ast/MemberNode.java: ditto. * net/loveruby/cflat/ast/PtrMemberNode.java: ditto. * net/loveruby/cflat/entity/Entity.java: remove #cannotLoad. * net/loveruby/cflat/entity/Function.java: ditto. * net/loveruby/cflat/entity/Variable.java: ditto. * net/loveruby/cflat/entity/Constant.java: ditto. * net/loveruby/cflat/ir/Addr.java: is not LHS node now. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4220 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
ced081c9c3
commit
3b29c039bd
81
ChangeLog
81
ChangeLog
|
|
@ -1,3 +1,84 @@
|
|||
Mon May 18 03:01:22 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/parser/Parser.jj: change function pointer
|
||||
syntax: int(*)(int,int) -> int(int,int)*. Function type is
|
||||
int(int,int).
|
||||
|
||||
* net/loveruby/cflat/parser/Parser.jj: function returns function
|
||||
type, not pointer to function.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeResolver.java: resolve all
|
||||
function headers first, then resolve bodies.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeResolver.java: generate a
|
||||
pointer for array-type expression.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeResolver.java: isDereferable ->
|
||||
isPointer.
|
||||
|
||||
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/compiler/DereferenceChecker.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/compiler/IRGenerator.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/compiler/IRGenerator.java:
|
||||
shouldEvaluatedToAddress -> isLoadable (check arrays and
|
||||
functions, not only arrays).
|
||||
|
||||
* net/loveruby/cflat/type/Type.java: remove #isDereferable.
|
||||
|
||||
* net/loveruby/cflat/type/UserType.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/type/ArrayType.java: is not a scalar.
|
||||
|
||||
* net/loveruby/cflat/type/ArrayType.java: is not dereferable
|
||||
itself.
|
||||
|
||||
* net/loveruby/cflat/type/PointerType.java: is incompatible with
|
||||
arrays.
|
||||
|
||||
* net/loveruby/cflat/type/IntegerType.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/type/FunctionType.java: is callable.
|
||||
|
||||
* net/loveruby/cflat/type/ParamTypeRefs.java: x[] -> x* for param
|
||||
types.
|
||||
|
||||
* net/loveruby/cflat/type/TypeTable.java: new method
|
||||
#getParamType.
|
||||
|
||||
* net/loveruby/cflat/ast/ExprNode.java: new method #isLvalue.
|
||||
|
||||
* net/loveruby/cflat/ast/ExprNode.java: new method #isAssignable.
|
||||
|
||||
* net/loveruby/cflat/ast/ExprNode.java: new method #isLoadable.
|
||||
|
||||
* net/loveruby/cflat/ast/CastNode.java: delegate them.
|
||||
|
||||
* net/loveruby/cflat/ast/LHSNode.java: new super class of LHS
|
||||
nodes.
|
||||
|
||||
* net/loveruby/cflat/ast/VariableNode.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/DereferenceNode.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/ArefNode.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/MemberNode.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/PtrMemberNode.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/entity/Entity.java: remove #cannotLoad.
|
||||
|
||||
* net/loveruby/cflat/entity/Function.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/entity/Variable.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/entity/Constant.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ir/Addr.java: is not LHS node now.
|
||||
|
||||
Sun May 17 16:37:26 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* import/dlfcn.hb: new declaration file dlfcn.hb.
|
||||
|
|
|
|||
|
|
@ -1,35 +1,22 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class ArefNode extends ExprNode {
|
||||
protected ExprNode expr, index;
|
||||
public class ArefNode extends LHSNode {
|
||||
private ExprNode expr, index;
|
||||
|
||||
public ArefNode(ExprNode expr, ExprNode index) {
|
||||
this.expr = expr;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return expr.type().baseType();
|
||||
}
|
||||
|
||||
public ExprNode expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public ExprNode index() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public boolean isAssignable() {
|
||||
return true;
|
||||
}
|
||||
public ExprNode expr() { return expr; }
|
||||
public ExprNode index() { return index; }
|
||||
|
||||
// isMultiDimension a[x][y][z] = true.
|
||||
// isMultiDimension a[x][y] = true.
|
||||
// isMultiDimension a[x] = false.
|
||||
public boolean isMultiDimension() {
|
||||
return (expr instanceof ArefNode) && !expr.type().isPointer();
|
||||
return (expr instanceof ArefNode) && !expr.origType().isPointer();
|
||||
}
|
||||
|
||||
// Returns base expression of (multi-dimension) array.
|
||||
|
|
@ -40,17 +27,19 @@ public class ArefNode extends ExprNode {
|
|||
|
||||
// element size of this (multi-dimension) array
|
||||
public long elementSize() {
|
||||
return type().allocSize();
|
||||
return origType().allocSize();
|
||||
}
|
||||
|
||||
public long length() {
|
||||
return ((ArrayType)expr.type()).length();
|
||||
return ((ArrayType)expr.origType()).length();
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
return false;
|
||||
protected Type origType() {
|
||||
return expr.origType().baseType();
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() { return false; }
|
||||
|
||||
public Location location() {
|
||||
return expr.location();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,8 @@ public class CastNode extends ExprNode {
|
|||
return expr;
|
||||
}
|
||||
|
||||
public boolean shouldEvaluatedToAddress() {
|
||||
return expr.shouldEvaluatedToAddress();
|
||||
}
|
||||
public boolean isLvalue() { return expr.isLvalue(); }
|
||||
public boolean isAssignable() { return expr.isAssignable(); }
|
||||
|
||||
public boolean isEffectiveCast() {
|
||||
return type().size() > expr.type().size();
|
||||
|
|
|
|||
|
|
@ -1,18 +1,35 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class DereferenceNode extends UnaryOpNode {
|
||||
public DereferenceNode(ExprNode n) {
|
||||
super("*", n);
|
||||
public class DereferenceNode extends LHSNode {
|
||||
private ExprNode expr;
|
||||
|
||||
public DereferenceNode(ExprNode expr) {
|
||||
this.expr = expr;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return expr().type().baseType();
|
||||
protected Type origType() {
|
||||
return expr.type().baseType();
|
||||
}
|
||||
|
||||
public ExprNode expr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public void setExpr(ExprNode expr) {
|
||||
this.expr = expr;
|
||||
}
|
||||
|
||||
public boolean isAssignable() { return true; }
|
||||
public boolean isConstantAddress() { return false; }
|
||||
|
||||
public Location location() {
|
||||
return expr.location();
|
||||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
d.printMember("expr", expr);
|
||||
}
|
||||
|
||||
public <S,E> E accept(ASTVisitor<S,E> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,16 @@ abstract public class ExprNode extends Node {
|
|||
}
|
||||
|
||||
abstract public Type type();
|
||||
protected Type origType() { return type(); }
|
||||
|
||||
public boolean isConstant() {
|
||||
return false;
|
||||
}
|
||||
public long allocSize() { return type().allocSize(); }
|
||||
|
||||
public boolean isConstant() { return false; }
|
||||
public boolean isParameter() { return false; }
|
||||
|
||||
public boolean isLvalue() { return false; }
|
||||
public boolean isAssignable() { return false; }
|
||||
public boolean isLoadable() { return false; }
|
||||
|
||||
public boolean isCallable() {
|
||||
try {
|
||||
|
|
@ -22,10 +28,10 @@ abstract public class ExprNode extends Node {
|
|||
}
|
||||
}
|
||||
|
||||
// #@@range/isDereferable{
|
||||
public boolean isDereferable() {
|
||||
// #@@range/isPointer{
|
||||
public boolean isPointer() {
|
||||
try {
|
||||
return type().isDereferable();
|
||||
return type().isPointer();
|
||||
}
|
||||
catch (SemanticError err) {
|
||||
return false;
|
||||
|
|
@ -33,18 +39,6 @@ abstract public class ExprNode extends Node {
|
|||
}
|
||||
// #@@}
|
||||
|
||||
public boolean isAssignable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isParameter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldEvaluatedToAddress() {
|
||||
return type().isArray();
|
||||
}
|
||||
|
||||
// used by IRGenerator
|
||||
public boolean isConstantAddress() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.Type;
|
||||
|
||||
abstract public class LHSNode extends ExprNode {
|
||||
protected Type type, origType;
|
||||
|
||||
public Type type() {
|
||||
return type != null ? type : origType();
|
||||
}
|
||||
|
||||
public void setType(Type t) {
|
||||
this.type = t;
|
||||
}
|
||||
|
||||
abstract protected Type origType();
|
||||
|
||||
public long allocSize() { return origType().allocSize(); }
|
||||
|
||||
public boolean isLvalue() { return true; }
|
||||
public boolean isAssignable() { return isLoadable(); }
|
||||
|
||||
public boolean isLoadable() {
|
||||
Type t = origType();
|
||||
return !t.isArray() && !t.isFunction();
|
||||
}
|
||||
|
||||
abstract public boolean isConstantAddress();
|
||||
}
|
||||
|
|
@ -3,19 +3,15 @@ import net.loveruby.cflat.type.Type;
|
|||
import net.loveruby.cflat.type.CompositeType;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
|
||||
public class MemberNode extends ExprNode {
|
||||
protected ExprNode expr;
|
||||
protected String member;
|
||||
public class MemberNode extends LHSNode {
|
||||
private ExprNode expr;
|
||||
private String member;
|
||||
|
||||
public MemberNode(ExprNode expr, String member) {
|
||||
this.expr = expr;
|
||||
this.member = member;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return baseType().memberType(member);
|
||||
}
|
||||
|
||||
public CompositeType baseType() {
|
||||
try {
|
||||
return expr.type().getCompositeType();
|
||||
|
|
@ -37,15 +33,11 @@ public class MemberNode extends ExprNode {
|
|||
return baseType().memberOffset(member);
|
||||
}
|
||||
|
||||
// #@@range/isAssignable{
|
||||
public boolean isAssignable() {
|
||||
return true;
|
||||
protected Type origType() {
|
||||
return baseType().memberType(member);
|
||||
}
|
||||
// #@@}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
return false;
|
||||
}
|
||||
public boolean isConstantAddress() { return false; }
|
||||
|
||||
public Location location() {
|
||||
return expr.location();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import net.loveruby.cflat.type.CompositeType;
|
|||
import net.loveruby.cflat.type.PointerType;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
|
||||
public class PtrMemberNode extends ExprNode {
|
||||
public class PtrMemberNode extends LHSNode {
|
||||
public ExprNode expr;
|
||||
public String member;
|
||||
|
||||
|
|
@ -13,10 +13,6 @@ public class PtrMemberNode extends ExprNode {
|
|||
this.member = member;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return dereferedCompositeType().memberType(member);
|
||||
}
|
||||
|
||||
public CompositeType dereferedCompositeType() {
|
||||
try {
|
||||
PointerType pt = expr.type().getPointerType();
|
||||
|
|
@ -45,18 +41,16 @@ public class PtrMemberNode extends ExprNode {
|
|||
return member;
|
||||
}
|
||||
|
||||
public boolean isAssignable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long offset() {
|
||||
return dereferedCompositeType().memberOffset(member);
|
||||
}
|
||||
|
||||
protected Type origType() {
|
||||
return dereferedCompositeType().memberType(member);
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() { return false; }
|
||||
|
||||
public Location location() {
|
||||
return expr.location();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package net.loveruby.cflat.ast;
|
|||
import net.loveruby.cflat.type.*;
|
||||
|
||||
public class TypeNode extends Node {
|
||||
protected TypeRef typeRef;
|
||||
protected Type type;
|
||||
TypeRef typeRef;
|
||||
Type type;
|
||||
|
||||
public TypeNode(TypeRef ref) {
|
||||
super();
|
||||
|
|
@ -24,12 +24,16 @@ public class TypeNode extends Node {
|
|||
}
|
||||
|
||||
public void setType(Type t) {
|
||||
if (isResolved()) throw new Error("TypeNode#setType called twice");
|
||||
if (type != null) {
|
||||
throw new Error("TypeNode#setType called twice");
|
||||
}
|
||||
type = t;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
if (type == null) throw new Error("TypeNode not resolved");
|
||||
if (type == null) {
|
||||
throw new Error("TypeNode not resolved: " + typeRef);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ import net.loveruby.cflat.type.Type;
|
|||
import net.loveruby.cflat.entity.Entity;
|
||||
import net.loveruby.cflat.entity.DefinedVariable;
|
||||
|
||||
public class VariableNode extends ExprNode {
|
||||
protected Location location;
|
||||
protected String name;
|
||||
protected Entity entity;
|
||||
public class VariableNode extends LHSNode {
|
||||
private Location location;
|
||||
private String name;
|
||||
private Entity entity;
|
||||
|
||||
public VariableNode(Location loc, String name) {
|
||||
super();
|
||||
this.location = loc;
|
||||
this.name = name;
|
||||
}
|
||||
|
|
@ -38,35 +37,28 @@ public class VariableNode extends ExprNode {
|
|||
entity = ent;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return entity().type();
|
||||
}
|
||||
|
||||
public TypeNode typeNode() {
|
||||
return entity().typeNode();
|
||||
}
|
||||
|
||||
public boolean isAssignable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isParameter() {
|
||||
return entity().isParameter();
|
||||
}
|
||||
|
||||
public boolean shouldEvaluatedToAddress() {
|
||||
return entity().cannotLoad();
|
||||
protected Type origType() {
|
||||
return entity().type();
|
||||
}
|
||||
|
||||
public boolean isConstantAddress() {
|
||||
return true;
|
||||
}
|
||||
public boolean isConstantAddress() { return true; }
|
||||
|
||||
public Location location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
if (type != null) {
|
||||
d.printMember("type", type);
|
||||
}
|
||||
d.printMember("name", name, isResolved());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,11 +129,11 @@ public class Compiler {
|
|||
new LocalResolver(errorHandler).resolve(ast);
|
||||
new TypeResolver(errorHandler).resolve(ast, typeTable);
|
||||
typeTable.semanticCheck(errorHandler);
|
||||
new DereferenceChecker(errorHandler).check(ast);
|
||||
if (opts.mode() == CompilerMode.DumpReference) {
|
||||
ast.dump();
|
||||
return ast;
|
||||
}
|
||||
new DereferenceChecker(errorHandler).check(ast);
|
||||
new TypeChecker(errorHandler).check(ast, typeTable);
|
||||
return ast;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class DereferenceChecker extends Visitor {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected void checkAssignment(AbstractAssignNode node) {
|
||||
private void checkAssignment(AbstractAssignNode node) {
|
||||
if (! node.lhs().isAssignable()) {
|
||||
semanticError(node, "invalid lhs expression");
|
||||
}
|
||||
|
|
@ -136,7 +136,7 @@ class DereferenceChecker extends Visitor {
|
|||
|
||||
public Void visit(ArefNode node) {
|
||||
super.visit(node);
|
||||
if (! node.expr().isDereferable()) {
|
||||
if (! node.expr().isPointer()) {
|
||||
semanticError(node, "indexing non-array/pointer expression");
|
||||
}
|
||||
return null;
|
||||
|
|
@ -150,7 +150,7 @@ class DereferenceChecker extends Visitor {
|
|||
|
||||
public Void visit(PtrMemberNode node) {
|
||||
super.visit(node);
|
||||
if (! node.expr().isDereferable()) {
|
||||
if (! node.expr().isPointer()) {
|
||||
undereferableError(node);
|
||||
}
|
||||
checkMemberRef(node, node.dereferedType(), node.member());
|
||||
|
|
@ -172,7 +172,7 @@ class DereferenceChecker extends Visitor {
|
|||
// #@@range/DereferenceNode{
|
||||
public Void visit(DereferenceNode node) {
|
||||
super.visit(node);
|
||||
if (! node.expr().isDereferable()) {
|
||||
if (! node.expr().isPointer()) {
|
||||
undereferableError(node);
|
||||
}
|
||||
return null;
|
||||
|
|
@ -182,8 +182,8 @@ class DereferenceChecker extends Visitor {
|
|||
// #@@range/AddressNode{
|
||||
public Void visit(AddressNode node) {
|
||||
super.visit(node);
|
||||
if (! node.expr().isAssignable()) {
|
||||
semanticError(node, "invalid LHS expression for &");
|
||||
if (! node.expr().isLvalue()) {
|
||||
semanticError(node, "invalid expression for &");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -197,6 +197,14 @@ class DereferenceChecker extends Visitor {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Void visit(CastNode node) {
|
||||
super.visit(node);
|
||||
if (node.type().isArray()) {
|
||||
semanticError(node, "cast specifies array type");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
|
|
|
|||
|
|
@ -482,7 +482,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
|||
switch (op) {
|
||||
case ADD:
|
||||
case SUB:
|
||||
if (lhsType.isDereferable()) {
|
||||
if (lhsType.isPointer()) {
|
||||
return new Bin(rhs.type(), Op.MUL,
|
||||
rhs, ptrDiff(lhsType.baseType().size()));
|
||||
}
|
||||
|
|
@ -565,11 +565,11 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
|||
Expr right = transformExpr(node.right());
|
||||
Expr left = transformExpr(node.left());
|
||||
if (node.operator().equals("+") || node.operator().equals("-")) {
|
||||
if (node.left().type().isDereferable()) {
|
||||
if (node.left().type().isPointer()) {
|
||||
right = new Bin(ptrDiffType(), Op.MUL,
|
||||
right, ptrDiff(node.left().type().baseType().size()));
|
||||
}
|
||||
else if (node.right().type().isDereferable()) {
|
||||
else if (node.right().type().isPointer()) {
|
||||
left = new Bin(ptrDiffType(), Op.MUL,
|
||||
left, ptrDiff(node.right().type().baseType().size()));
|
||||
}
|
||||
|
|
@ -626,9 +626,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
|||
Expr addr = new Bin(pointer(), Op.ADD,
|
||||
addressOf(transformExpr(node.expr())),
|
||||
intValue(node.offset()));
|
||||
return node.shouldEvaluatedToAddress()
|
||||
? addr
|
||||
: deref(addr, node.type());
|
||||
return node.isLoadable() ? deref(addr, node.type()) : addr;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
|
@ -636,7 +634,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
|||
Expr addr = new Bin(pointer(), Op.ADD,
|
||||
transformExpr(node.expr()),
|
||||
intValue(node.offset()));
|
||||
return node.shouldEvaluatedToAddress() ? addr : deref(addr, node.type());
|
||||
return node.isLoadable() ? deref(addr, node.type()) : addr;
|
||||
}
|
||||
|
||||
public Expr visit(DereferenceNode node) {
|
||||
|
|
@ -645,12 +643,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
|||
|
||||
public Expr visit(AddressNode node) {
|
||||
Expr e = transformExpr(node.expr());
|
||||
if (node.expr().shouldEvaluatedToAddress()) {
|
||||
return e;
|
||||
}
|
||||
else {
|
||||
return addressOf(e);
|
||||
}
|
||||
return node.expr().isLoadable() ? addressOf(e) : e;
|
||||
}
|
||||
|
||||
public Expr visit(CastNode node) {
|
||||
|
|
@ -669,7 +662,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
|||
}
|
||||
|
||||
public Expr visit(SizeofExprNode node) {
|
||||
return intValue(node.expr().type().allocSize());
|
||||
return intValue(node.expr().allocSize());
|
||||
}
|
||||
|
||||
public Expr visit(SizeofTypeNode node) {
|
||||
|
|
@ -681,7 +674,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
|||
return transformExpr(node.entity().value());
|
||||
}
|
||||
Var var = new Var(varType(node.type()), node.entity());
|
||||
return node.shouldEvaluatedToAddress() ? addressOf(var) : var;
|
||||
return node.isLoadable() ? var : addressOf(var);
|
||||
}
|
||||
|
||||
public Expr visit(IntegerLiteralNode node) {
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ class TypeChecker extends Visitor {
|
|||
if (! checkLHS(node.lhs())) return null;
|
||||
if (! checkRHS(node.rhs())) return null;
|
||||
if (node.operator().equals("+") || node.operator().equals("-")) {
|
||||
if (node.lhs().type().isDereferable()) {
|
||||
if (node.lhs().type().isPointer()) {
|
||||
mustBeInteger(node.rhs(), node.operator());
|
||||
node.setRHS(integralPromotedExpr(node.rhs()));
|
||||
return null;
|
||||
|
|
@ -290,7 +290,7 @@ class TypeChecker extends Visitor {
|
|||
* * pointer - integer
|
||||
*/
|
||||
protected void expectsSameIntegerOrPointerDiff(BinaryOpNode node) {
|
||||
if (node.left().type().isDereferable()) {
|
||||
if (node.left().type().isPointer()) {
|
||||
if (node.left().type().baseType().isVoid()) {
|
||||
wrongTypeError(node.left(), node.operator());
|
||||
return;
|
||||
|
|
@ -300,7 +300,7 @@ class TypeChecker extends Visitor {
|
|||
node.setRight(integralPromotedExpr(node.right()));
|
||||
node.setType(node.left().type());
|
||||
}
|
||||
else if (node.right().type().isDereferable()) {
|
||||
else if (node.right().type().isPointer()) {
|
||||
if (node.operator().equals("-")) {
|
||||
error(node, "invalid operation integer-pointer");
|
||||
return;
|
||||
|
|
@ -342,13 +342,13 @@ class TypeChecker extends Visitor {
|
|||
protected void expectsComparableScalars(BinaryOpNode node) {
|
||||
if (! mustBeScalar(node.left(), node.operator())) return;
|
||||
if (! mustBeScalar(node.right(), node.operator())) return;
|
||||
if (node.left().type().isDereferable()) {
|
||||
if (node.left().type().isPointer()) {
|
||||
ExprNode right = forcePointerType(node.left(), node.right());
|
||||
node.setRight(right);
|
||||
node.setType(node.left().type());
|
||||
return;
|
||||
}
|
||||
if (node.right().type().isDereferable()) {
|
||||
if (node.right().type().isPointer()) {
|
||||
ExprNode left = forcePointerType(node.right(), node.left());
|
||||
node.setLeft(left);
|
||||
node.setType(node.right().type());
|
||||
|
|
@ -433,7 +433,7 @@ class TypeChecker extends Visitor {
|
|||
}
|
||||
node.setAmount(1);
|
||||
}
|
||||
else if (node.expr().type().isDereferable()) {
|
||||
else if (node.expr().type().isPointer()) {
|
||||
if (node.expr().type().baseType().isVoid()) {
|
||||
// We cannot increment/decrement void*
|
||||
wrongTypeError(node.expr(), node.operator());
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@ public class TypeResolver extends Visitor
|
|||
for (Entity e : ast.entities()) {
|
||||
e.accept(this);
|
||||
}
|
||||
|
||||
for (DefinedVariable var : ast.definedVariables()) {
|
||||
if (var.hasInitializer()) {
|
||||
visitExpr(var.initializer());
|
||||
}
|
||||
}
|
||||
for (Constant c : ast.constants()) {
|
||||
visitExpr(c.value());
|
||||
}
|
||||
for (DefinedFunction f : ast.definedFunctions()) {
|
||||
visitStmt(f.body());
|
||||
}
|
||||
// #@@}
|
||||
}
|
||||
// #@@}
|
||||
|
|
@ -100,9 +112,6 @@ public class TypeResolver extends Visitor
|
|||
// #@@range/DefinedVariable{
|
||||
public Void visit(DefinedVariable var) {
|
||||
bindType(var.typeNode());
|
||||
if (var.hasInitializer()) {
|
||||
visitExpr(var.initializer());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
|
@ -114,14 +123,12 @@ public class TypeResolver extends Visitor
|
|||
|
||||
public Void visit(Constant c) {
|
||||
bindType(c.typeNode());
|
||||
visitExpr(c.value());
|
||||
return null;
|
||||
}
|
||||
|
||||
// #@@range/DefinedFunction{
|
||||
public Void visit(DefinedFunction func) {
|
||||
resolveFunctionHeader(func);
|
||||
visitStmt(func.body());
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
|
@ -135,11 +142,8 @@ public class TypeResolver extends Visitor
|
|||
protected void resolveFunctionHeader(Function func) {
|
||||
bindType(func.typeNode());
|
||||
for (Parameter param : func.parameters()) {
|
||||
Type t = typeTable.get(param.typeNode().typeRef());
|
||||
// arrays must be converted to pointers in a function parameter.
|
||||
if (t.isArray()) {
|
||||
t = typeTable.pointerTo(t.getArrayType().baseType());
|
||||
}
|
||||
Type t = typeTable.getParamType(param.typeNode().typeRef());
|
||||
param.typeNode().setType(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -151,7 +155,12 @@ public class TypeResolver extends Visitor
|
|||
|
||||
public Void visit(BlockNode node) {
|
||||
for (DefinedVariable var : node.variables()) {
|
||||
var.accept(this);
|
||||
bindType(var.typeNode());
|
||||
}
|
||||
for (DefinedVariable var : node.variables()) {
|
||||
if (var.hasInitializer()) {
|
||||
visitExpr(var.initializer());
|
||||
}
|
||||
}
|
||||
visitStmts(node.stmts());
|
||||
return null;
|
||||
|
|
@ -159,11 +168,10 @@ public class TypeResolver extends Visitor
|
|||
|
||||
public Void visit(AddressNode node) {
|
||||
super.visit(node);
|
||||
// to avoid SemanticError which occurs when getting type of
|
||||
// expr which is not assignable.
|
||||
try {
|
||||
Type base = node.expr().type();
|
||||
if (node.expr().shouldEvaluatedToAddress()) {
|
||||
if (! node.expr().isLoadable()) {
|
||||
// node.expr.type is already pointer.
|
||||
node.setType(base);
|
||||
}
|
||||
else {
|
||||
|
|
@ -177,6 +185,54 @@ public class TypeResolver extends Visitor
|
|||
return null;
|
||||
}
|
||||
|
||||
public Void visit(DereferenceNode node) {
|
||||
super.visit(node);
|
||||
handleImplicitAddress(node);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(MemberNode node) {
|
||||
super.visit(node);
|
||||
handleImplicitAddress(node);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(PtrMemberNode node) {
|
||||
super.visit(node);
|
||||
handleImplicitAddress(node);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(ArefNode node) {
|
||||
super.visit(node);
|
||||
handleImplicitAddress(node);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(VariableNode node) {
|
||||
super.visit(node);
|
||||
handleImplicitAddress(node);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleImplicitAddress(LHSNode node) {
|
||||
try {
|
||||
if (! node.isLoadable()) {
|
||||
Type t = node.type();
|
||||
if (t.isArray()) {
|
||||
// int[4] ary; ary; should generate int*
|
||||
node.setType(typeTable.pointerTo(t.baseType()));
|
||||
}
|
||||
else {
|
||||
node.setType(typeTable.pointerTo(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SemanticError err) {
|
||||
// #isLoadable may cause SemanticError, ignore it
|
||||
}
|
||||
}
|
||||
|
||||
public Void visit(CastNode node) {
|
||||
bindType(node.typeNode());
|
||||
super.visit(node);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public class Constant extends Entity {
|
|||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean cannotLoad() { return false; }
|
||||
public boolean isAssignable() { return false; }
|
||||
public boolean isDefined() { return true; }
|
||||
public boolean isInitialized() { return true; }
|
||||
public boolean isConstant() { return true; }
|
||||
|
|
|
|||
|
|
@ -70,8 +70,6 @@ abstract public class Entity
|
|||
return (nRefered > 0);
|
||||
}
|
||||
|
||||
abstract public boolean cannotLoad();
|
||||
|
||||
public void setMemref(MemoryReference mem) {
|
||||
this.memref = mem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,27 +14,19 @@ abstract public class Function extends Entity {
|
|||
super(priv, t, name);
|
||||
}
|
||||
|
||||
public boolean isFunction() { return true; }
|
||||
public boolean isInitialized() { return true; }
|
||||
|
||||
abstract public boolean isDefined();
|
||||
abstract public List<Parameter> parameters();
|
||||
|
||||
public FunctionType functionType() {
|
||||
return type().getPointerType().baseType().getFunctionType();
|
||||
}
|
||||
|
||||
public Type returnType() {
|
||||
return functionType().returnType();
|
||||
return type().getFunctionType().returnType();
|
||||
}
|
||||
|
||||
public boolean isVoid() {
|
||||
return returnType().isVoid();
|
||||
}
|
||||
|
||||
public boolean cannotLoad() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCallingSymbol(Symbol sym) {
|
||||
if (this.callingSymbol != null) {
|
||||
throw new Error("must not happen: Function#callingSymbol was set again");
|
||||
|
|
|
|||
|
|
@ -6,8 +6,4 @@ abstract public class Variable extends Entity {
|
|||
public Variable(boolean priv, TypeNode type, String name) {
|
||||
super(priv, type, name);
|
||||
}
|
||||
|
||||
public boolean cannotLoad() {
|
||||
return type().isArray();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,6 @@ public class Addr extends Expr {
|
|||
return entity.memref();
|
||||
}
|
||||
|
||||
public Addr addressNode(Type type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Entity getEntityForce() {
|
||||
return entity;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -536,18 +536,16 @@ Constant defconst():
|
|||
DefinedFunction defun():
|
||||
{
|
||||
boolean priv;
|
||||
TypeRef ref;
|
||||
TypeRef ret;
|
||||
String n;
|
||||
Params ps;
|
||||
BlockNode body;
|
||||
}
|
||||
{
|
||||
priv=storage() ref=typeref() n=name() "(" ps=params() ")" body=block()
|
||||
priv=storage() ret=typeref() n=name() "(" ps=params() ")" body=block()
|
||||
{
|
||||
ParamTypeRefs paramref = ps.parametersTypeRef();
|
||||
TypeNode t = new TypeNode(new PointerTypeRef(
|
||||
new FunctionTypeRef(ref, paramref)));
|
||||
return new DefinedFunction(priv, t, n, ps, body);
|
||||
TypeRef t = new FunctionTypeRef(ret, ps.parametersTypeRef());
|
||||
return new DefinedFunction(priv, new TypeNode(t), n, ps, body);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
|
@ -692,17 +690,15 @@ Slot slot():
|
|||
// #@@range/funcdecl{
|
||||
UndefinedFunction funcdecl():
|
||||
{
|
||||
TypeRef ref;
|
||||
TypeRef ret;
|
||||
String n;
|
||||
Params ps;
|
||||
}
|
||||
{
|
||||
<EXTERN> ref=typeref() n=name() "(" ps=params() ")" ";"
|
||||
<EXTERN> ret=typeref() n=name() "(" ps=params() ")" ";"
|
||||
{
|
||||
ParamTypeRefs paramref = ps.parametersTypeRef();
|
||||
TypeNode t = new TypeNode(new PointerTypeRef(
|
||||
new FunctionTypeRef(ref, paramref)));
|
||||
return new UndefinedFunction(t, n, ps);
|
||||
TypeRef t = new FunctionTypeRef(ret, ps.parametersTypeRef());
|
||||
return new UndefinedFunction(new TypeNode(t), n, ps);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
|
@ -749,9 +745,9 @@ TypeRef typeref():
|
|||
{
|
||||
ref = new PointerTypeRef(ref);
|
||||
}
|
||||
| "(" "*" ")" "(" params=param_typerefs() ")"
|
||||
| "(" params=param_typerefs() ")"
|
||||
{
|
||||
ref = new PointerTypeRef(new FunctionTypeRef(ref, params));
|
||||
ref = new FunctionTypeRef(ref, params);
|
||||
}
|
||||
)*
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ public class ArrayType extends Type {
|
|||
}
|
||||
|
||||
public boolean isArray() { return true; }
|
||||
public boolean isDereferable() { return true; }
|
||||
public boolean isScalar() { return true; }
|
||||
public boolean isScalar() { return false; }
|
||||
public boolean isSigned() { return false; }
|
||||
|
||||
public boolean isAllocatedArray() {
|
||||
|
|
@ -66,12 +65,12 @@ public class ArrayType extends Type {
|
|||
|
||||
public boolean isSameType(Type other) {
|
||||
// length is not important
|
||||
if (! other.isDereferable()) return false;
|
||||
if (!other.isPointer() && !other.isArray()) return false;
|
||||
return baseType.isSameType(other.baseType());
|
||||
}
|
||||
|
||||
public boolean isCompatible(Type target) {
|
||||
if (! target.isDereferable()) return false;
|
||||
if (!target.isPointer() && !target.isArray()) return false;
|
||||
if (target.baseType().isVoid()) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -80,7 +79,7 @@ public class ArrayType extends Type {
|
|||
}
|
||||
|
||||
public boolean isCastableTo(Type target) {
|
||||
return target.isDereferable();
|
||||
return target.isPointer() || target.isArray();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ public class FunctionType extends Type {
|
|||
}
|
||||
|
||||
public boolean isFunction() { return true; }
|
||||
public boolean isCallable() { return true; }
|
||||
|
||||
public boolean isSameType(Type other) {
|
||||
if (! other.isFunction()) return false;
|
||||
|
|
@ -68,7 +69,7 @@ public class FunctionType extends Type {
|
|||
String sep = "";
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(returnType.toString());
|
||||
buf.append(" (*)(");
|
||||
buf.append("(");
|
||||
for (Type t : paramTypes.types()) {
|
||||
buf.append(sep);
|
||||
buf.append(t.toString());
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class IntegerType extends Type {
|
|||
}
|
||||
|
||||
public boolean isCastableTo(Type target) {
|
||||
return (target.isInteger() || target.isDereferable());
|
||||
return (target.isInteger() || target.isPointer());
|
||||
}
|
||||
|
||||
public long size() {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public class ParamTypeRefs extends ParamSlots<TypeRef> {
|
|||
public ParamTypes internTypes(TypeTable table) {
|
||||
List<Type> types = new ArrayList<Type>();
|
||||
for (TypeRef ref : paramDescriptors) {
|
||||
types.add(table.get(ref));
|
||||
types.add(table.getParamType(ref));
|
||||
}
|
||||
return new ParamTypes(location, types, vararg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ public class PointerType extends Type {
|
|||
public boolean isPointer() { return true; }
|
||||
public boolean isScalar() { return true; }
|
||||
public boolean isSigned() { return false; }
|
||||
// #@@range/isDereferable{
|
||||
public boolean isDereferable() { return true; }
|
||||
// #@@}
|
||||
public boolean isCallable() { return baseType.isFunction(); }
|
||||
|
||||
public long size() {
|
||||
|
|
@ -31,12 +28,12 @@ public class PointerType extends Type {
|
|||
}
|
||||
|
||||
public boolean isSameType(Type other) {
|
||||
if (! other.isDereferable()) return false;
|
||||
if (!other.isPointer()) return false;
|
||||
return baseType.isSameType(other.baseType());
|
||||
}
|
||||
|
||||
public boolean isCompatible(Type other) {
|
||||
if (! other.isDereferable()) return false;
|
||||
if (!other.isPointer()) return false;
|
||||
if (baseType.isVoid()) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -47,7 +44,7 @@ public class PointerType extends Type {
|
|||
}
|
||||
|
||||
public boolean isCastableTo(Type other) {
|
||||
return other.isDereferable() || other.isInteger();
|
||||
return other.isPointer() || other.isInteger();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ public abstract class Type {
|
|||
public boolean isFunction() { return false; }
|
||||
|
||||
// Ability methods (unary)
|
||||
public boolean isDereferable() { return false; }
|
||||
public boolean isAllocatedArray() { return false; }
|
||||
public boolean isIncompleteArray() { return false; }
|
||||
public boolean isScalar() { return false; }
|
||||
|
|
|
|||
|
|
@ -90,6 +90,12 @@ public class TypeTable {
|
|||
return type;
|
||||
}
|
||||
|
||||
// array is really a pointer on parameters.
|
||||
public Type getParamType(TypeRef ref) {
|
||||
Type t = get(ref);
|
||||
return t.isArray() ? pointerTo(t.baseType()) : t;
|
||||
}
|
||||
|
||||
public int intSize() {
|
||||
return this.intSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ public class UserType extends NamedType {
|
|||
public boolean isUserType() { return true; }
|
||||
public boolean isFunction() { return realType().isFunction(); }
|
||||
|
||||
public boolean isDereferable() { return realType().isDereferable(); }
|
||||
public boolean isCallable() { return realType().isCallable(); }
|
||||
public boolean isScalar() { return realType().isScalar(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,28 @@
|
|||
import stdio;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
int (*)(char*) f;
|
||||
int (char*, ...)* f;
|
||||
|
||||
f = puts;
|
||||
f = printf;
|
||||
f("OK");
|
||||
|
||||
f = &printf;
|
||||
f(";OK");
|
||||
|
||||
f = myputs;
|
||||
f(";OK");
|
||||
|
||||
f = &myputs;
|
||||
f(";OK");
|
||||
|
||||
puts("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
myputs(char *s, ...)
|
||||
{
|
||||
return printf("%s", s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
import stdio;
|
||||
|
||||
void myputs(char* str) { puts(str); }
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
void (*)(char*) f;
|
||||
|
||||
f = myputs;
|
||||
f("OK");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import stdio;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int (*)(char*) f;
|
||||
|
||||
f = &puts;
|
||||
f("OK");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import stdio;
|
||||
|
||||
void myputs(char* str) { puts(str); }
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
void (*)(char*) f;
|
||||
|
||||
f = &myputs;
|
||||
f("OK");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ test_10_assign() {
|
|||
assert_out "3;4;3;12;4;1;1;7;5;1;4;e;H;76;75;1;3;6;82;81" ./opassign
|
||||
assert_out "0;1;2;2;3;3;4;5;5" ./inc
|
||||
assert_out "4;3;2;2;1;1;0" ./dec
|
||||
assert_compile_success textwrite.cb
|
||||
assert_compile_error textwrite.cb
|
||||
}
|
||||
|
||||
test_12_if() {
|
||||
|
|
@ -244,10 +244,7 @@ test_25_block() {
|
|||
}
|
||||
|
||||
test_26_funcptr() {
|
||||
assert_out "OK" ./funcptr
|
||||
assert_out "OK" ./funcptr2
|
||||
assert_out "OK" ./funcptr3
|
||||
assert_out "OK" ./funcptr4
|
||||
assert_out "OK;OK;OK;OK" ./funcptr
|
||||
assert_compile_error defun-semcheck.cb
|
||||
assert_compile_error defun-semcheck2.cb
|
||||
assert_compile_error defun-semcheck3.cb
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ typedef struct s struct_s;
|
|||
typedef union u union_u;
|
||||
typedef int[8] ints8;
|
||||
typedef int* intptr;
|
||||
typedef int (*)(char*) msgfunc;
|
||||
typedef int (char*)* msgfunc;
|
||||
typedef sint sint2;
|
||||
|
||||
int
|
||||
|
|
|
|||
Loading…
Reference in New Issue