1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-08 13:31:03 +00:00

Implemented support for complex casts and parsing complex type names for sizeof(). #121

This commit is contained in:
jespergravgaard 2021-05-13 10:26:33 +02:00
parent 2ffa6e3ca8
commit 541b92c55b
15 changed files with 1728 additions and 1119 deletions

View File

@ -64,10 +64,16 @@ declType
: directive* type directive*
;
typeSpecifier
: type #typeSpecifierSimple
| typeSpecifier ASTERISK #typeSpecifierPointer
| typeSpecifier BRACKET_BEGIN (expr)? BRACKET_END #typeSpecifierArray
typeName
: type typeNameDeclarator
;
typeNameDeclarator
: #typeNameDeclaratorName
| typeNameDeclarator PAR_BEGIN parameterListDecl? PAR_END #typeNameDeclaratorProcedure
| typeNameDeclarator BRACKET_BEGIN (expr)? BRACKET_END #typeNameDeclaratorArray
| ASTERISK directive* typeNameDeclarator #typeNameDeclaratorPointer
| PAR_BEGIN typeNameDeclarator PAR_END #typeNameDeclaratorPar
;
declarator
@ -125,8 +131,8 @@ parameterListDecl
: parameterDecl (COMMA parameterDecl)* ;
parameterDecl
: declType declarator #parameterDeclType
| SIMPLETYPE #parameterDeclVoid
: declType declarator #parameterDeclTypeDeclarator
| typeName #parameterDeclTypeName
| PARAM_LIST #parameterDeclList
;
@ -215,11 +221,11 @@ expr
| expr DOT NAME #exprDot
| expr '->' NAME #exprArrow
| expr PAR_BEGIN parameterList? PAR_END #exprCall
| SIZEOF PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprSizeOf
| TYPEID PAR_BEGIN ( expr | typeSpecifier ) PAR_END #exprTypeId
| SIZEOF PAR_BEGIN ( expr | typeName ) PAR_END #exprSizeOf
| TYPEID PAR_BEGIN ( expr | typeName ) PAR_END #exprTypeId
| DEFINED PAR_BEGIN? NAME PAR_END? #exprDefined
| expr BRACKET_BEGIN commaExpr BRACKET_END #exprArray
| PAR_BEGIN typeSpecifier PAR_END expr #exprCast
| PAR_BEGIN typeName PAR_END expr #exprCast
| ('--' | '++' ) expr #exprPreMod
| expr ('--' | '++' ) #exprPostMod
| ASTERISK expr #exprPtr

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -138,37 +138,73 @@ public class KickCParserBaseListener implements KickCParserListener {
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeSpecifierSimple(KickCParser.TypeSpecifierSimpleContext ctx) { }
@Override public void enterTypeName(KickCParser.TypeNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeSpecifierSimple(KickCParser.TypeSpecifierSimpleContext ctx) { }
@Override public void exitTypeName(KickCParser.TypeNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeSpecifierPointer(KickCParser.TypeSpecifierPointerContext ctx) { }
@Override public void enterTypeNameDeclaratorArray(KickCParser.TypeNameDeclaratorArrayContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeSpecifierPointer(KickCParser.TypeSpecifierPointerContext ctx) { }
@Override public void exitTypeNameDeclaratorArray(KickCParser.TypeNameDeclaratorArrayContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeSpecifierArray(KickCParser.TypeSpecifierArrayContext ctx) { }
@Override public void enterTypeNameDeclaratorPar(KickCParser.TypeNameDeclaratorParContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeSpecifierArray(KickCParser.TypeSpecifierArrayContext ctx) { }
@Override public void exitTypeNameDeclaratorPar(KickCParser.TypeNameDeclaratorParContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeNameDeclaratorName(KickCParser.TypeNameDeclaratorNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeNameDeclaratorName(KickCParser.TypeNameDeclaratorNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeNameDeclaratorProcedure(KickCParser.TypeNameDeclaratorProcedureContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeNameDeclaratorProcedure(KickCParser.TypeNameDeclaratorProcedureContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterTypeNameDeclaratorPointer(KickCParser.TypeNameDeclaratorPointerContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitTypeNameDeclaratorPointer(KickCParser.TypeNameDeclaratorPointerContext ctx) { }
/**
* {@inheritDoc}
*
@ -426,25 +462,25 @@ public class KickCParserBaseListener implements KickCParserListener {
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { }
@Override public void enterParameterDeclTypeDeclarator(KickCParser.ParameterDeclTypeDeclaratorContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { }
@Override public void exitParameterDeclTypeDeclarator(KickCParser.ParameterDeclTypeDeclaratorContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { }
@Override public void enterParameterDeclTypeName(KickCParser.ParameterDeclTypeNameContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { }
@Override public void exitParameterDeclTypeName(KickCParser.ParameterDeclTypeNameContext ctx) { }
/**
* {@inheritDoc}
*

View File

@ -89,21 +89,42 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeSpecifierSimple(KickCParser.TypeSpecifierSimpleContext ctx) { return visitChildren(ctx); }
@Override public T visitTypeName(KickCParser.TypeNameContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeSpecifierPointer(KickCParser.TypeSpecifierPointerContext ctx) { return visitChildren(ctx); }
@Override public T visitTypeNameDeclaratorArray(KickCParser.TypeNameDeclaratorArrayContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeSpecifierArray(KickCParser.TypeSpecifierArrayContext ctx) { return visitChildren(ctx); }
@Override public T visitTypeNameDeclaratorPar(KickCParser.TypeNameDeclaratorParContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeNameDeclaratorName(KickCParser.TypeNameDeclaratorNameContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeNameDeclaratorProcedure(KickCParser.TypeNameDeclaratorProcedureContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeNameDeclaratorPointer(KickCParser.TypeNameDeclaratorPointerContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
@ -257,14 +278,14 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { return visitChildren(ctx); }
@Override public T visitParameterDeclTypeDeclarator(KickCParser.ParameterDeclTypeDeclaratorContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { return visitChildren(ctx); }
@Override public T visitParameterDeclTypeName(KickCParser.ParameterDeclTypeNameContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*

View File

@ -114,41 +114,75 @@ public interface KickCParserListener extends ParseTreeListener {
*/
void exitDeclType(KickCParser.DeclTypeContext ctx);
/**
* Enter a parse tree produced by the {@code typeSpecifierSimple}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Enter a parse tree produced by {@link KickCParser#typeName}.
* @param ctx the parse tree
*/
void enterTypeSpecifierSimple(KickCParser.TypeSpecifierSimpleContext ctx);
void enterTypeName(KickCParser.TypeNameContext ctx);
/**
* Exit a parse tree produced by the {@code typeSpecifierSimple}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Exit a parse tree produced by {@link KickCParser#typeName}.
* @param ctx the parse tree
*/
void exitTypeSpecifierSimple(KickCParser.TypeSpecifierSimpleContext ctx);
void exitTypeName(KickCParser.TypeNameContext ctx);
/**
* Enter a parse tree produced by the {@code typeSpecifierPointer}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Enter a parse tree produced by the {@code typeNameDeclaratorArray}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void enterTypeSpecifierPointer(KickCParser.TypeSpecifierPointerContext ctx);
void enterTypeNameDeclaratorArray(KickCParser.TypeNameDeclaratorArrayContext ctx);
/**
* Exit a parse tree produced by the {@code typeSpecifierPointer}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Exit a parse tree produced by the {@code typeNameDeclaratorArray}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void exitTypeSpecifierPointer(KickCParser.TypeSpecifierPointerContext ctx);
void exitTypeNameDeclaratorArray(KickCParser.TypeNameDeclaratorArrayContext ctx);
/**
* Enter a parse tree produced by the {@code typeSpecifierArray}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Enter a parse tree produced by the {@code typeNameDeclaratorPar}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void enterTypeSpecifierArray(KickCParser.TypeSpecifierArrayContext ctx);
void enterTypeNameDeclaratorPar(KickCParser.TypeNameDeclaratorParContext ctx);
/**
* Exit a parse tree produced by the {@code typeSpecifierArray}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Exit a parse tree produced by the {@code typeNameDeclaratorPar}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void exitTypeSpecifierArray(KickCParser.TypeSpecifierArrayContext ctx);
void exitTypeNameDeclaratorPar(KickCParser.TypeNameDeclaratorParContext ctx);
/**
* Enter a parse tree produced by the {@code typeNameDeclaratorName}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void enterTypeNameDeclaratorName(KickCParser.TypeNameDeclaratorNameContext ctx);
/**
* Exit a parse tree produced by the {@code typeNameDeclaratorName}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void exitTypeNameDeclaratorName(KickCParser.TypeNameDeclaratorNameContext ctx);
/**
* Enter a parse tree produced by the {@code typeNameDeclaratorProcedure}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void enterTypeNameDeclaratorProcedure(KickCParser.TypeNameDeclaratorProcedureContext ctx);
/**
* Exit a parse tree produced by the {@code typeNameDeclaratorProcedure}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void exitTypeNameDeclaratorProcedure(KickCParser.TypeNameDeclaratorProcedureContext ctx);
/**
* Enter a parse tree produced by the {@code typeNameDeclaratorPointer}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void enterTypeNameDeclaratorPointer(KickCParser.TypeNameDeclaratorPointerContext ctx);
/**
* Exit a parse tree produced by the {@code typeNameDeclaratorPointer}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
*/
void exitTypeNameDeclaratorPointer(KickCParser.TypeNameDeclaratorPointerContext ctx);
/**
* Enter a parse tree produced by the {@code declaratorPointer}
* labeled alternative in {@link KickCParser#declarator}.
@ -384,29 +418,29 @@ public interface KickCParserListener extends ParseTreeListener {
*/
void exitParameterListDecl(KickCParser.ParameterListDeclContext ctx);
/**
* Enter a parse tree produced by the {@code parameterDeclType}
* Enter a parse tree produced by the {@code parameterDeclTypeDeclarator}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
*/
void enterParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
void enterParameterDeclTypeDeclarator(KickCParser.ParameterDeclTypeDeclaratorContext ctx);
/**
* Exit a parse tree produced by the {@code parameterDeclType}
* Exit a parse tree produced by the {@code parameterDeclTypeDeclarator}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
*/
void exitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
void exitParameterDeclTypeDeclarator(KickCParser.ParameterDeclTypeDeclaratorContext ctx);
/**
* Enter a parse tree produced by the {@code parameterDeclVoid}
* Enter a parse tree produced by the {@code parameterDeclTypeName}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
*/
void enterParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
void enterParameterDeclTypeName(KickCParser.ParameterDeclTypeNameContext ctx);
/**
* Exit a parse tree produced by the {@code parameterDeclVoid}
* Exit a parse tree produced by the {@code parameterDeclTypeName}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
*/
void exitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
void exitParameterDeclTypeName(KickCParser.ParameterDeclTypeNameContext ctx);
/**
* Enter a parse tree produced by the {@code parameterDeclList}
* labeled alternative in {@link KickCParser#parameterDecl}.

View File

@ -75,26 +75,46 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
*/
T visitDeclType(KickCParser.DeclTypeContext ctx);
/**
* Visit a parse tree produced by the {@code typeSpecifierSimple}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Visit a parse tree produced by {@link KickCParser#typeName}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeSpecifierSimple(KickCParser.TypeSpecifierSimpleContext ctx);
T visitTypeName(KickCParser.TypeNameContext ctx);
/**
* Visit a parse tree produced by the {@code typeSpecifierPointer}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Visit a parse tree produced by the {@code typeNameDeclaratorArray}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeSpecifierPointer(KickCParser.TypeSpecifierPointerContext ctx);
T visitTypeNameDeclaratorArray(KickCParser.TypeNameDeclaratorArrayContext ctx);
/**
* Visit a parse tree produced by the {@code typeSpecifierArray}
* labeled alternative in {@link KickCParser#typeSpecifier}.
* Visit a parse tree produced by the {@code typeNameDeclaratorPar}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeSpecifierArray(KickCParser.TypeSpecifierArrayContext ctx);
T visitTypeNameDeclaratorPar(KickCParser.TypeNameDeclaratorParContext ctx);
/**
* Visit a parse tree produced by the {@code typeNameDeclaratorName}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeNameDeclaratorName(KickCParser.TypeNameDeclaratorNameContext ctx);
/**
* Visit a parse tree produced by the {@code typeNameDeclaratorProcedure}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeNameDeclaratorProcedure(KickCParser.TypeNameDeclaratorProcedureContext ctx);
/**
* Visit a parse tree produced by the {@code typeNameDeclaratorPointer}
* labeled alternative in {@link KickCParser#typeNameDeclarator}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeNameDeclaratorPointer(KickCParser.TypeNameDeclaratorPointerContext ctx);
/**
* Visit a parse tree produced by the {@code declaratorPointer}
* labeled alternative in {@link KickCParser#declarator}.
@ -234,19 +254,19 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
*/
T visitParameterListDecl(KickCParser.ParameterListDeclContext ctx);
/**
* Visit a parse tree produced by the {@code parameterDeclType}
* Visit a parse tree produced by the {@code parameterDeclTypeDeclarator}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
T visitParameterDeclTypeDeclarator(KickCParser.ParameterDeclTypeDeclaratorContext ctx);
/**
* Visit a parse tree produced by the {@code parameterDeclVoid}
* Visit a parse tree produced by the {@code parameterDeclTypeName}
* labeled alternative in {@link KickCParser#parameterDecl}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
T visitParameterDeclTypeName(KickCParser.ParameterDeclTypeNameContext ctx);
/**
* Visit a parse tree produced by the {@code parameterDeclList}
* labeled alternative in {@link KickCParser#parameterDecl}.

View File

@ -491,6 +491,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
if(SymbolType.VOID.equals(parameter.type))
throw new CompileError("Illegal void parameter.", statementSource);
// Handle parameters without a name in the declaration
if(parameter.name==null)
throw new CompileError("Illegal unnamed parameter.", statementSource);
VariableBuilder varBuilder = new VariableBuilder(parameter.name, getCurrentScope(), true, parameter.type, null, currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
final Variable paramVar = varBuilder.build();
parameterList.add(paramVar);
@ -509,7 +513,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
}
@Override
public Object visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) {
public Object visitParameterDeclTypeDeclarator(KickCParser.ParameterDeclTypeDeclaratorContext ctx) {
this.visit(ctx.declType());
this.visit(ctx.declarator());
ParameterDecl paramDecl = new ParameterDecl(varDecl.getVarName(), varDecl.getEffectiveType());
@ -518,11 +522,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
}
@Override
public Object visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) {
if(!SymbolType.VOID.getTypeName().equals(ctx.SIMPLETYPE().getText())) {
throw new CompileError("Illegal unnamed parameter " + ctx.SIMPLETYPE().getText(), new StatementSource(ctx));
}
return new ParameterDecl(null, SymbolType.VOID);
public Object visitParameterDeclTypeName(KickCParser.ParameterDeclTypeNameContext ctx) {
SymbolType paramType = (SymbolType) this.visit(ctx.typeName());
return new ParameterDecl(null, paramType);
}
@Override
@ -1945,6 +1947,16 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
@Override
public Object visitTypeName(KickCParser.TypeNameContext ctx) {
varDeclPush();
this.visit(ctx.type());
this.visit(ctx.typeNameDeclarator());
final SymbolType type = varDecl.getEffectiveType();
varDeclPop();
return type;
}
@Override
public Object visitDeclaratorPointer(KickCParser.DeclaratorPointerContext ctx) {
final SymbolType elementDeclType = varDecl.getEffectiveType();
@ -1955,6 +1967,16 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
@Override
public Object visitTypeNameDeclaratorPointer(KickCParser.TypeNameDeclaratorPointerContext ctx) {
final SymbolType elementDeclType = varDecl.getEffectiveType();
SymbolTypePointer pointerType = new SymbolTypePointer(elementDeclType);
final List<Directive> typeDirectives = getDirectives(ctx.directive());
varDecl.setVarDeclTypeAndDirectives(pointerType, typeDirectives);
this.visit(ctx.typeNameDeclarator());
return varDecl.getEffectiveType();
}
@Override
public Object visitDeclaratorArray(KickCParser.DeclaratorArrayContext ctx) {
this.visit(ctx.declarator());
@ -1976,18 +1998,50 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
@Override
public Object visitTypeNameDeclaratorArray(KickCParser.TypeNameDeclaratorArrayContext ctx) {
this.visit(ctx.typeNameDeclarator());
// Handle array type declaration by updating the declared type and the array spec
ArraySpec arraySpec;
if(ctx.expr() != null) {
varDeclPush();
RValue sizeVal = (RValue) visit(ctx.expr());
if(!(sizeVal instanceof ConstantValue))
throw new CompileError(sizeVal.toString() + " is not constant or is not defined", new StatementSource(ctx));
varDeclPop();
arraySpec = new ArraySpec((ConstantValue) sizeVal);
} else {
arraySpec = new ArraySpec();
}
final SymbolType elementDeclType = varDecl.getEffectiveType();
SymbolType arrayDeclType = new SymbolTypePointer(elementDeclType, arraySpec, false, false);
varDecl.setVarDeclType(arrayDeclType);
return varDecl.getEffectiveType();
}
@Override
public Object visitDeclaratorPar(KickCParser.DeclaratorParContext ctx) {
this.visit(ctx.declarator());
return null;
}
@Override
public Object visitTypeNameDeclaratorPar(KickCParser.TypeNameDeclaratorParContext ctx) {
this.visit(ctx.typeNameDeclarator());
return varDecl.getEffectiveType();
}
@Override
public Object visitDeclaratorName(KickCParser.DeclaratorNameContext ctx) {
varDecl.setVarName(ctx.getText());
return null;
}
@Override
public Object visitTypeNameDeclaratorName(KickCParser.TypeNameDeclaratorNameContext ctx) {
return null;
}
@Override
public Object visitDeclaratorProcedure(KickCParser.DeclaratorProcedureContext ctx) {
List<ParameterDecl> parameters = new ArrayList<>();
@ -2012,6 +2066,30 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
@Override
public Object visitTypeNameDeclaratorProcedure(KickCParser.TypeNameDeclaratorProcedureContext ctx) {
List<ParameterDecl> parameters = new ArrayList<>();
List<SymbolType> paramTypes = new ArrayList<>();
if(ctx.parameterListDecl() != null)
for(KickCParser.ParameterDeclContext parameterDeclContext : ctx.parameterListDecl().parameterDecl()) {
varDeclPush();
ParameterDecl paramDecl = (ParameterDecl) this.visit(parameterDeclContext);
// Handle parameter list with "VOID"
if(SymbolType.VOID.equals(paramDecl.type) && ctx.parameterListDecl().parameterDecl().size()==1)
; // Ignore the void parameter
else {
paramTypes.add(paramDecl.type);
parameters.add(paramDecl);
}
varDeclPop();
}
SymbolType returnType = varDecl.getEffectiveType();
varDecl.setVarDeclType(new SymbolTypeProcedure(returnType, paramTypes));
varDecl.setParameters(parameters);
visit(ctx.typeNameDeclarator());
return varDecl.getEffectiveType();
}
@Override
public Object visitTypeNamedRef(KickCParser.TypeNamedRefContext ctx) {
Scope typeDefScope = program.getScope().getTypeDefScope();
@ -2206,32 +2284,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return structMemberRef;
}
@Override
public SymbolType visitTypeSpecifierSimple(KickCParser.TypeSpecifierSimpleContext ctx) {
varDeclPush();
this.visit(ctx.type());
final SymbolType type = varDecl.getEffectiveType();
varDeclPop();
return type;
}
@Override
public SymbolType visitTypeSpecifierPointer(KickCParser.TypeSpecifierPointerContext ctx) {
return new SymbolTypePointer((SymbolType) this.visit(ctx.typeSpecifier()));
}
@Override
public SymbolType visitTypeSpecifierArray(KickCParser.TypeSpecifierArrayContext ctx) {
SymbolType elementType = (SymbolType) visit(ctx.typeSpecifier());
if(ctx.expr() != null)
throw new InternalError("Not implemented!");
return new SymbolTypePointer(elementType);
}
@Override
public RValue visitExprCast(KickCParser.ExprCastContext ctx) {
RValue child = (RValue) this.visit(ctx.expr());
SymbolType castType = (SymbolType) this.visit(ctx.typeSpecifier());
SymbolType castType = (SymbolType) this.visit(ctx.typeName());
Operator operator = Operators.getCastUnary(castType);
if(child instanceof ConstantValue) {
consumeExpr(child);
@ -2243,9 +2299,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
@Override
public Object visitExprSizeOf(KickCParser.ExprSizeOfContext ctx) {
if(ctx.typeSpecifier() != null) {
if(ctx.typeName() != null) {
// sizeof(type) - add directly
SymbolType type = (SymbolType) this.visit(ctx.typeSpecifier());
SymbolType type = (SymbolType) this.visit(ctx.typeName());
return SizeOfConstants.getSizeOfConstantVar(program.getScope(), type);
} else {
// sizeof(expression) - add a unary expression to be resolved later
@ -2261,9 +2317,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
@Override
public Object visitExprTypeId(KickCParser.ExprTypeIdContext ctx) {
if(ctx.typeSpecifier() != null) {
if(ctx.typeName() != null) {
// typeid(type) - add directly
SymbolType type = (SymbolType) this.visit(ctx.typeSpecifier());
SymbolType type = (SymbolType) this.visit(ctx.typeName());
return OperatorTypeId.getTypeIdConstantVar(program.getScope(), type);
} else {
// typeid(expression) - add a unary expression to be resolved later

View File

@ -273,7 +273,7 @@ public class TestPreprocessor {
@Override
public Object visitExprCast(KickCParser.ExprCastContext ctx) {
out.append("cast(");
out.append(ctx.typeSpecifier().getText());
out.append(ctx.typeName().getText());
out.append(",");
this.visit(ctx.expr());
out.append(")");

View File

@ -9,6 +9,11 @@ import java.io.IOException;
*/
public class TestProgramsFast extends TestPrograms {
@Test
public void testProcedureDeclare11() throws IOException {
compileAndCompare("procedure-declare-11.c");
}
@Test
public void testProcedureDeclare10() throws IOException {
compileAndCompare("procedure-declare-10.c");

View File

@ -0,0 +1,14 @@
// Pointer to pointer to procedure without typedef (uses a very complex cast)
// Define const pointer to pointer to no-arg-noreturn procedure
void (** const IRQ)(void) = (void(**)(void))0x314;
char * const SCREEN = (char*)0x0400;
__interrupt void irq() {
SCREEN[0]++;
}
void main() {
*IRQ = &irq;
}

View File

@ -0,0 +1,28 @@
// Pointer to pointer to procedure without typedef (uses a very complex cast)
// Commodore 64 PRG executable file
.file [name="procedure-declare-11.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Define const pointer to pointer to no-arg-noreturn procedure
.label IRQ = $314
.label SCREEN = $400
.segment Code
main: {
// *IRQ = &irq
lda #<irq
sta IRQ
lda #>irq
sta IRQ+1
// }
rts
}
irq: {
// SCREEN[0]++;
inc SCREEN
// }
jmp $ea81
}

View File

@ -0,0 +1,16 @@
void main()
main: scope:[main] from
[0] *IRQ = &irq
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
__interrupt(rom_min_c64) void irq()
irq: scope:[irq] from
[2] *SCREEN = ++ *SCREEN
to:irq::@return
irq::@return: scope:[irq] from irq
[3] return
to:@return

View File

@ -0,0 +1,203 @@
CONTROL FLOW GRAPH SSA
__interrupt(rom_min_c64) void irq()
irq: scope:[irq] from
SCREEN[0] = ++ SCREEN[0]
to:irq::@return
irq::@return: scope:[irq] from irq
return
to:@return
void main()
main: scope:[main] from __start
*IRQ = &irq
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
constant void()** const IRQ = (void()**)$314
constant byte* const SCREEN = (byte*)$400
void __start()
__interrupt(rom_min_c64) void irq()
void main()
Adding number conversion cast (unumber) 0 in SCREEN[0] = ++ SCREEN[0]
Adding number conversion cast (unumber) 0 in SCREEN[0] = ++ SCREEN[(unumber)0]
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (void()**) 788
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = ++ SCREEN[0]
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = ++ *SCREEN
Successful SSA optimization PassNSimplifyExpressionWithZero
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *IRQ = &irq
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
__interrupt(rom_min_c64) void irq()
irq: scope:[irq] from
[2] *SCREEN = ++ *SCREEN
to:irq::@return
irq::@return: scope:[irq] from irq
[3] return
to:@return
VARIABLE REGISTER WEIGHTS
__interrupt(rom_min_c64) void irq()
void main()
Initial phi equivalence classes
Complete equivalence classes
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *IRQ = &irq [ ] ( [ ] { } ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [irq]
Uplift Scope [main]
Uplift Scope []
Uplifting [irq] best 60 combination
Uplifting [main] best 60 combination
Uplifting [] best 60 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Pointer to pointer to procedure without typedef (uses a very complex cast)
// Upstart
// Commodore 64 PRG executable file
.file [name="procedure-declare-11.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
// Define const pointer to pointer to no-arg-noreturn procedure
.label IRQ = $314
.label SCREEN = $400
.segment Code
// main
main: {
// [0] *IRQ = &irq -- _deref_qprc1=pprc2
lda #<irq
sta IRQ
lda #>irq
sta IRQ+1
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// irq
irq: {
// interrupt(isr_rom_min_c64_entry) -- isr_rom_min_c64_entry
// [2] *SCREEN = ++ *SCREEN -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
jmp __breturn
// irq::@return
__breturn:
// [3] return
// interrupt(isr_rom_min_c64_exit) -- isr_rom_min_c64_exit
jmp $ea81
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
constant void()** const IRQ = (void()**) 788
constant byte* const SCREEN = (byte*) 1024
__interrupt(rom_min_c64) void irq()
void main()
FINAL ASSEMBLER
Score: 54
// File Comments
// Pointer to pointer to procedure without typedef (uses a very complex cast)
// Upstart
// Commodore 64 PRG executable file
.file [name="procedure-declare-11.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
// Define const pointer to pointer to no-arg-noreturn procedure
.label IRQ = $314
.label SCREEN = $400
.segment Code
// main
main: {
// *IRQ = &irq
// [0] *IRQ = &irq -- _deref_qprc1=pprc2
lda #<irq
sta IRQ
lda #>irq
sta IRQ+1
// main::@return
// }
// [1] return
rts
}
// irq
irq: {
// interrupt(isr_rom_min_c64_entry) -- isr_rom_min_c64_entry
// SCREEN[0]++;
// [2] *SCREEN = ++ *SCREEN -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
// irq::@return
// }
// [3] return
// interrupt(isr_rom_min_c64_exit) -- isr_rom_min_c64_exit
jmp $ea81
}
// File Data

View File

@ -0,0 +1,5 @@
constant void()** const IRQ = (void()**) 788
constant byte* const SCREEN = (byte*) 1024
__interrupt(rom_min_c64) void irq()
void main()