mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-08-08 13:25:12 +00:00
Added syntax for procedure calling conventions - and a pragma changing the current calling convention. Added two tests. Changed Pass1 procedure-stuff to only handle the PHI calling convention. #316
This commit is contained in:
@@ -12,7 +12,6 @@ import java.util.List;
|
|||||||
/** Symbol describing a procedure/function */
|
/** Symbol describing a procedure/function */
|
||||||
public class Procedure extends Scope {
|
public class Procedure extends Scope {
|
||||||
|
|
||||||
|
|
||||||
/** The return type. {@link SymbolType#VOID} if the procedure does not return a value. */
|
/** The return type. {@link SymbolType#VOID} if the procedure does not return a value. */
|
||||||
private final SymbolType returnType;
|
private final SymbolType returnType;
|
||||||
/** The names of the parameters of the procedure. */
|
/** The names of the parameters of the procedure. */
|
||||||
@@ -28,13 +27,53 @@ public class Procedure extends Scope {
|
|||||||
/** The code segment to put the procedure into. */
|
/** The code segment to put the procedure into. */
|
||||||
private String codeSegment;
|
private String codeSegment;
|
||||||
|
|
||||||
public Procedure(String name, SymbolType returnType, Scope parentScope, String codeSegment, String dataSegment) {
|
/** The method for passing parameters and return value to the procedure. */
|
||||||
|
public enum CallingConvension {
|
||||||
|
/** Parameters and return value handled through call PHI-transitions. */
|
||||||
|
PHI_CALL("__phicall"),
|
||||||
|
/** Parameters and return value over the stack. */
|
||||||
|
STACK_CALL("__stackcall");
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
CallingConvension(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a calling convention by name. */
|
||||||
|
public static CallingConvension getCallingConvension(String name) {
|
||||||
|
for(CallingConvension value : CallingConvension.values()) {
|
||||||
|
if(value.getName().equalsIgnoreCase(name)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The calling convention used for this procedure. */
|
||||||
|
private CallingConvension callingConvension;
|
||||||
|
|
||||||
|
public Procedure(String name, SymbolType returnType, Scope parentScope, String codeSegment, String dataSegment, CallingConvension callingConvension) {
|
||||||
super(name, parentScope, dataSegment);
|
super(name, parentScope, dataSegment);
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
this.declaredInline = false;
|
this.declaredInline = false;
|
||||||
this.interruptType = null;
|
this.interruptType = null;
|
||||||
this.comments = new ArrayList<>();
|
this.comments = new ArrayList<>();
|
||||||
this.codeSegment = codeSegment;
|
this.codeSegment = codeSegment;
|
||||||
|
this.callingConvension = callingConvension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallingConvension getCallingConvension() {
|
||||||
|
return callingConvension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallingConvension(CallingConvension callingConvension) {
|
||||||
|
this.callingConvension = callingConvension;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCodeSegment() {
|
public String getCodeSegment() {
|
||||||
@@ -165,6 +204,9 @@ public class Procedure extends Scope {
|
|||||||
if(declaredInline) {
|
if(declaredInline) {
|
||||||
res.append("inline ");
|
res.append("inline ");
|
||||||
}
|
}
|
||||||
|
if(!callingConvension.equals(CallingConvension.PHI_CALL)) {
|
||||||
|
res.append(getCallingConvension().getName()).append(" ");
|
||||||
|
}
|
||||||
if(interruptType != null) {
|
if(interruptType != null) {
|
||||||
res.append("interrupt(" + interruptType + ")");
|
res.append("interrupt(" + interruptType + ")");
|
||||||
}
|
}
|
||||||
|
@@ -280,8 +280,8 @@ public abstract class Scope implements Symbol, Serializable {
|
|||||||
return (BlockScope) getSymbol(name);
|
return (BlockScope) getSymbol(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Procedure addProcedure(String name, SymbolType type, String codeSegment, String dataSegment) {
|
public Procedure addProcedure(String name, SymbolType type, String codeSegment, String dataSegment, Procedure.CallingConvension callingConvension) {
|
||||||
return add(new Procedure(name, type, this, codeSegment, dataSegment));
|
return add(new Procedure(name, type, this, codeSegment, dataSegment, callingConvension));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Procedure getProcedure(String name) {
|
public Procedure getProcedure(String name) {
|
||||||
|
@@ -81,6 +81,8 @@ REGISTER: 'register' ;
|
|||||||
INLINE: 'inline' ;
|
INLINE: 'inline' ;
|
||||||
VOLATILE: 'volatile' ;
|
VOLATILE: 'volatile' ;
|
||||||
INTERRUPT: 'interrupt' ;
|
INTERRUPT: 'interrupt' ;
|
||||||
|
CALLING: 'calling';
|
||||||
|
CALLINGCONVENTION: '__stackcall' | '__phicall' ;
|
||||||
IF: 'if' ;
|
IF: 'if' ;
|
||||||
ELSE: 'else' ;
|
ELSE: 'else' ;
|
||||||
WHILE: 'while' ;
|
WHILE: 'while' ;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -54,84 +54,86 @@ REGISTER=53
|
|||||||
INLINE=54
|
INLINE=54
|
||||||
VOLATILE=55
|
VOLATILE=55
|
||||||
INTERRUPT=56
|
INTERRUPT=56
|
||||||
IF=57
|
CALLING=57
|
||||||
ELSE=58
|
CALLINGCONVENTION=58
|
||||||
WHILE=59
|
IF=59
|
||||||
DO=60
|
ELSE=60
|
||||||
FOR=61
|
WHILE=61
|
||||||
SWITCH=62
|
DO=62
|
||||||
RETURN=63
|
FOR=63
|
||||||
BREAK=64
|
SWITCH=64
|
||||||
CONTINUE=65
|
RETURN=65
|
||||||
ASM=66
|
BREAK=66
|
||||||
DEFAULT=67
|
CONTINUE=67
|
||||||
CASE=68
|
ASM=68
|
||||||
STRUCT=69
|
DEFAULT=69
|
||||||
ENUM=70
|
CASE=70
|
||||||
SIZEOF=71
|
STRUCT=71
|
||||||
TYPEID=72
|
ENUM=72
|
||||||
KICKASM=73
|
SIZEOF=73
|
||||||
RESOURCE=74
|
TYPEID=74
|
||||||
USES=75
|
KICKASM=75
|
||||||
CLOBBERS=76
|
RESOURCE=76
|
||||||
BYTES=77
|
USES=77
|
||||||
CYCLES=78
|
CLOBBERS=78
|
||||||
LOGIC_NOT=79
|
BYTES=79
|
||||||
SIGNEDNESS=80
|
CYCLES=80
|
||||||
SIMPLETYPE=81
|
LOGIC_NOT=81
|
||||||
BOOLEAN=82
|
SIGNEDNESS=82
|
||||||
KICKASM_BODY=83
|
SIMPLETYPE=83
|
||||||
STRING=84
|
BOOLEAN=84
|
||||||
CHAR=85
|
KICKASM_BODY=85
|
||||||
NUMBER=86
|
STRING=86
|
||||||
NUMFLOAT=87
|
CHAR=87
|
||||||
BINFLOAT=88
|
NUMBER=88
|
||||||
DECFLOAT=89
|
NUMFLOAT=89
|
||||||
HEXFLOAT=90
|
BINFLOAT=90
|
||||||
NUMINT=91
|
DECFLOAT=91
|
||||||
BININTEGER=92
|
HEXFLOAT=92
|
||||||
DECINTEGER=93
|
NUMINT=93
|
||||||
HEXINTEGER=94
|
BININTEGER=94
|
||||||
NAME=95
|
DECINTEGER=95
|
||||||
WS=96
|
HEXINTEGER=96
|
||||||
COMMENT_LINE=97
|
NAME=97
|
||||||
COMMENT_BLOCK=98
|
WS=98
|
||||||
ASM_BYTE=99
|
COMMENT_LINE=99
|
||||||
ASM_MNEMONIC=100
|
COMMENT_BLOCK=100
|
||||||
ASM_IMM=101
|
ASM_BYTE=101
|
||||||
ASM_COLON=102
|
ASM_MNEMONIC=102
|
||||||
ASM_COMMA=103
|
ASM_IMM=103
|
||||||
ASM_PAR_BEGIN=104
|
ASM_COLON=104
|
||||||
ASM_PAR_END=105
|
ASM_COMMA=105
|
||||||
ASM_BRACKET_BEGIN=106
|
ASM_PAR_BEGIN=106
|
||||||
ASM_BRACKET_END=107
|
ASM_PAR_END=107
|
||||||
ASM_DOT=108
|
ASM_BRACKET_BEGIN=108
|
||||||
ASM_SHIFT_LEFT=109
|
ASM_BRACKET_END=109
|
||||||
ASM_SHIFT_RIGHT=110
|
ASM_DOT=110
|
||||||
ASM_PLUS=111
|
ASM_SHIFT_LEFT=111
|
||||||
ASM_MINUS=112
|
ASM_SHIFT_RIGHT=112
|
||||||
ASM_LESS_THAN=113
|
ASM_PLUS=113
|
||||||
ASM_GREATER_THAN=114
|
ASM_MINUS=114
|
||||||
ASM_MULTIPLY=115
|
ASM_LESS_THAN=115
|
||||||
ASM_DIVIDE=116
|
ASM_GREATER_THAN=116
|
||||||
ASM_CURLY_BEGIN=117
|
ASM_MULTIPLY=117
|
||||||
ASM_CURLY_END=118
|
ASM_DIVIDE=118
|
||||||
ASM_NUMBER=119
|
ASM_CURLY_BEGIN=119
|
||||||
ASM_NUMFLOAT=120
|
ASM_CURLY_END=120
|
||||||
ASM_BINFLOAT=121
|
ASM_NUMBER=121
|
||||||
ASM_DECFLOAT=122
|
ASM_NUMFLOAT=122
|
||||||
ASM_HEXFLOAT=123
|
ASM_BINFLOAT=123
|
||||||
ASM_NUMINT=124
|
ASM_DECFLOAT=124
|
||||||
ASM_BININTEGER=125
|
ASM_HEXFLOAT=125
|
||||||
ASM_DECINTEGER=126
|
ASM_NUMINT=126
|
||||||
ASM_HEXINTEGER=127
|
ASM_BININTEGER=127
|
||||||
ASM_CHAR=128
|
ASM_DECINTEGER=128
|
||||||
ASM_MULTI_REL=129
|
ASM_HEXINTEGER=129
|
||||||
ASM_MULTI_NAME=130
|
ASM_CHAR=130
|
||||||
ASM_NAME=131
|
ASM_MULTI_REL=131
|
||||||
ASM_WS=132
|
ASM_MULTI_NAME=132
|
||||||
ASM_COMMENT_LINE=133
|
ASM_NAME=133
|
||||||
ASM_COMMENT_BLOCK=134
|
ASM_WS=134
|
||||||
|
ASM_COMMENT_LINE=135
|
||||||
|
ASM_COMMENT_BLOCK=136
|
||||||
';'=8
|
';'=8
|
||||||
'..'=11
|
'..'=11
|
||||||
'?'=12
|
'?'=12
|
||||||
@@ -169,28 +171,29 @@ ASM_COMMENT_BLOCK=134
|
|||||||
'inline'=54
|
'inline'=54
|
||||||
'volatile'=55
|
'volatile'=55
|
||||||
'interrupt'=56
|
'interrupt'=56
|
||||||
'if'=57
|
'calling'=57
|
||||||
'else'=58
|
'if'=59
|
||||||
'while'=59
|
'else'=60
|
||||||
'do'=60
|
'while'=61
|
||||||
'for'=61
|
'do'=62
|
||||||
'switch'=62
|
'for'=63
|
||||||
'return'=63
|
'switch'=64
|
||||||
'break'=64
|
'return'=65
|
||||||
'continue'=65
|
'break'=66
|
||||||
'asm'=66
|
'continue'=67
|
||||||
'default'=67
|
'asm'=68
|
||||||
'case'=68
|
'default'=69
|
||||||
'struct'=69
|
'case'=70
|
||||||
'enum'=70
|
'struct'=71
|
||||||
'sizeof'=71
|
'enum'=72
|
||||||
'typeid'=72
|
'sizeof'=73
|
||||||
'kickasm'=73
|
'typeid'=74
|
||||||
'resource'=74
|
'kickasm'=75
|
||||||
'uses'=75
|
'resource'=76
|
||||||
'clobbers'=76
|
'uses'=77
|
||||||
'bytes'=77
|
'clobbers'=78
|
||||||
'cycles'=78
|
'bytes'=79
|
||||||
'!'=79
|
'cycles'=80
|
||||||
'.byte'=99
|
'!'=81
|
||||||
'#'=101
|
'.byte'=101
|
||||||
|
'#'=103
|
||||||
|
@@ -91,6 +91,7 @@ globalDirective
|
|||||||
| (PRAGMA CODESEG) PAR_BEGIN NAME PAR_END #globalDirectiveCodeSeg
|
| (PRAGMA CODESEG) PAR_BEGIN NAME PAR_END #globalDirectiveCodeSeg
|
||||||
| (PRAGMA DATASEG) PAR_BEGIN NAME PAR_END #globalDirectiveDataSeg
|
| (PRAGMA DATASEG) PAR_BEGIN NAME PAR_END #globalDirectiveDataSeg
|
||||||
| (PRAGMA ENCODING) PAR_BEGIN NAME PAR_END #globalDirectiveEncoding
|
| (PRAGMA ENCODING) PAR_BEGIN NAME PAR_END #globalDirectiveEncoding
|
||||||
|
| (PRAGMA CALLING) PAR_BEGIN CALLINGCONVENTION PAR_END #globalDirectiveCalling
|
||||||
;
|
;
|
||||||
|
|
||||||
directive
|
directive
|
||||||
@@ -103,6 +104,7 @@ directive
|
|||||||
| VOLATILE #directiveVolatile
|
| VOLATILE #directiveVolatile
|
||||||
| INTERRUPT ( PAR_BEGIN NAME PAR_END )? #directiveInterrupt
|
| INTERRUPT ( PAR_BEGIN NAME PAR_END )? #directiveInterrupt
|
||||||
| RESERVE PAR_BEGIN NUMBER ( COMMA NUMBER )* PAR_END #directiveReserveZp
|
| RESERVE PAR_BEGIN NUMBER ( COMMA NUMBER )* PAR_END #directiveReserveZp
|
||||||
|
| CALLINGCONVENTION #directiveCallingConvention
|
||||||
;
|
;
|
||||||
|
|
||||||
stmtSeq
|
stmtSeq
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -54,84 +54,86 @@ REGISTER=53
|
|||||||
INLINE=54
|
INLINE=54
|
||||||
VOLATILE=55
|
VOLATILE=55
|
||||||
INTERRUPT=56
|
INTERRUPT=56
|
||||||
IF=57
|
CALLING=57
|
||||||
ELSE=58
|
CALLINGCONVENTION=58
|
||||||
WHILE=59
|
IF=59
|
||||||
DO=60
|
ELSE=60
|
||||||
FOR=61
|
WHILE=61
|
||||||
SWITCH=62
|
DO=62
|
||||||
RETURN=63
|
FOR=63
|
||||||
BREAK=64
|
SWITCH=64
|
||||||
CONTINUE=65
|
RETURN=65
|
||||||
ASM=66
|
BREAK=66
|
||||||
DEFAULT=67
|
CONTINUE=67
|
||||||
CASE=68
|
ASM=68
|
||||||
STRUCT=69
|
DEFAULT=69
|
||||||
ENUM=70
|
CASE=70
|
||||||
SIZEOF=71
|
STRUCT=71
|
||||||
TYPEID=72
|
ENUM=72
|
||||||
KICKASM=73
|
SIZEOF=73
|
||||||
RESOURCE=74
|
TYPEID=74
|
||||||
USES=75
|
KICKASM=75
|
||||||
CLOBBERS=76
|
RESOURCE=76
|
||||||
BYTES=77
|
USES=77
|
||||||
CYCLES=78
|
CLOBBERS=78
|
||||||
LOGIC_NOT=79
|
BYTES=79
|
||||||
SIGNEDNESS=80
|
CYCLES=80
|
||||||
SIMPLETYPE=81
|
LOGIC_NOT=81
|
||||||
BOOLEAN=82
|
SIGNEDNESS=82
|
||||||
KICKASM_BODY=83
|
SIMPLETYPE=83
|
||||||
STRING=84
|
BOOLEAN=84
|
||||||
CHAR=85
|
KICKASM_BODY=85
|
||||||
NUMBER=86
|
STRING=86
|
||||||
NUMFLOAT=87
|
CHAR=87
|
||||||
BINFLOAT=88
|
NUMBER=88
|
||||||
DECFLOAT=89
|
NUMFLOAT=89
|
||||||
HEXFLOAT=90
|
BINFLOAT=90
|
||||||
NUMINT=91
|
DECFLOAT=91
|
||||||
BININTEGER=92
|
HEXFLOAT=92
|
||||||
DECINTEGER=93
|
NUMINT=93
|
||||||
HEXINTEGER=94
|
BININTEGER=94
|
||||||
NAME=95
|
DECINTEGER=95
|
||||||
WS=96
|
HEXINTEGER=96
|
||||||
COMMENT_LINE=97
|
NAME=97
|
||||||
COMMENT_BLOCK=98
|
WS=98
|
||||||
ASM_BYTE=99
|
COMMENT_LINE=99
|
||||||
ASM_MNEMONIC=100
|
COMMENT_BLOCK=100
|
||||||
ASM_IMM=101
|
ASM_BYTE=101
|
||||||
ASM_COLON=102
|
ASM_MNEMONIC=102
|
||||||
ASM_COMMA=103
|
ASM_IMM=103
|
||||||
ASM_PAR_BEGIN=104
|
ASM_COLON=104
|
||||||
ASM_PAR_END=105
|
ASM_COMMA=105
|
||||||
ASM_BRACKET_BEGIN=106
|
ASM_PAR_BEGIN=106
|
||||||
ASM_BRACKET_END=107
|
ASM_PAR_END=107
|
||||||
ASM_DOT=108
|
ASM_BRACKET_BEGIN=108
|
||||||
ASM_SHIFT_LEFT=109
|
ASM_BRACKET_END=109
|
||||||
ASM_SHIFT_RIGHT=110
|
ASM_DOT=110
|
||||||
ASM_PLUS=111
|
ASM_SHIFT_LEFT=111
|
||||||
ASM_MINUS=112
|
ASM_SHIFT_RIGHT=112
|
||||||
ASM_LESS_THAN=113
|
ASM_PLUS=113
|
||||||
ASM_GREATER_THAN=114
|
ASM_MINUS=114
|
||||||
ASM_MULTIPLY=115
|
ASM_LESS_THAN=115
|
||||||
ASM_DIVIDE=116
|
ASM_GREATER_THAN=116
|
||||||
ASM_CURLY_BEGIN=117
|
ASM_MULTIPLY=117
|
||||||
ASM_CURLY_END=118
|
ASM_DIVIDE=118
|
||||||
ASM_NUMBER=119
|
ASM_CURLY_BEGIN=119
|
||||||
ASM_NUMFLOAT=120
|
ASM_CURLY_END=120
|
||||||
ASM_BINFLOAT=121
|
ASM_NUMBER=121
|
||||||
ASM_DECFLOAT=122
|
ASM_NUMFLOAT=122
|
||||||
ASM_HEXFLOAT=123
|
ASM_BINFLOAT=123
|
||||||
ASM_NUMINT=124
|
ASM_DECFLOAT=124
|
||||||
ASM_BININTEGER=125
|
ASM_HEXFLOAT=125
|
||||||
ASM_DECINTEGER=126
|
ASM_NUMINT=126
|
||||||
ASM_HEXINTEGER=127
|
ASM_BININTEGER=127
|
||||||
ASM_CHAR=128
|
ASM_DECINTEGER=128
|
||||||
ASM_MULTI_REL=129
|
ASM_HEXINTEGER=129
|
||||||
ASM_MULTI_NAME=130
|
ASM_CHAR=130
|
||||||
ASM_NAME=131
|
ASM_MULTI_REL=131
|
||||||
ASM_WS=132
|
ASM_MULTI_NAME=132
|
||||||
ASM_COMMENT_LINE=133
|
ASM_NAME=133
|
||||||
ASM_COMMENT_BLOCK=134
|
ASM_WS=134
|
||||||
|
ASM_COMMENT_LINE=135
|
||||||
|
ASM_COMMENT_BLOCK=136
|
||||||
';'=8
|
';'=8
|
||||||
'..'=11
|
'..'=11
|
||||||
'?'=12
|
'?'=12
|
||||||
@@ -169,28 +171,29 @@ ASM_COMMENT_BLOCK=134
|
|||||||
'inline'=54
|
'inline'=54
|
||||||
'volatile'=55
|
'volatile'=55
|
||||||
'interrupt'=56
|
'interrupt'=56
|
||||||
'if'=57
|
'calling'=57
|
||||||
'else'=58
|
'if'=59
|
||||||
'while'=59
|
'else'=60
|
||||||
'do'=60
|
'while'=61
|
||||||
'for'=61
|
'do'=62
|
||||||
'switch'=62
|
'for'=63
|
||||||
'return'=63
|
'switch'=64
|
||||||
'break'=64
|
'return'=65
|
||||||
'continue'=65
|
'break'=66
|
||||||
'asm'=66
|
'continue'=67
|
||||||
'default'=67
|
'asm'=68
|
||||||
'case'=68
|
'default'=69
|
||||||
'struct'=69
|
'case'=70
|
||||||
'enum'=70
|
'struct'=71
|
||||||
'sizeof'=71
|
'enum'=72
|
||||||
'typeid'=72
|
'sizeof'=73
|
||||||
'kickasm'=73
|
'typeid'=74
|
||||||
'resource'=74
|
'kickasm'=75
|
||||||
'uses'=75
|
'resource'=76
|
||||||
'clobbers'=76
|
'uses'=77
|
||||||
'bytes'=77
|
'clobbers'=78
|
||||||
'cycles'=78
|
'bytes'=79
|
||||||
'!'=79
|
'cycles'=80
|
||||||
'.byte'=99
|
'!'=81
|
||||||
'#'=101
|
'.byte'=101
|
||||||
|
'#'=103
|
||||||
|
@@ -301,6 +301,18 @@ public class KickCParserBaseListener implements KickCParserListener {
|
|||||||
* <p>The default implementation does nothing.</p>
|
* <p>The default implementation does nothing.</p>
|
||||||
*/
|
*/
|
||||||
@Override public void exitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx) { }
|
@Override public void exitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx) { }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>The default implementation does nothing.</p>
|
||||||
|
*/
|
||||||
|
@Override public void enterGlobalDirectiveCalling(KickCParser.GlobalDirectiveCallingContext ctx) { }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>The default implementation does nothing.</p>
|
||||||
|
*/
|
||||||
|
@Override public void exitGlobalDirectiveCalling(KickCParser.GlobalDirectiveCallingContext ctx) { }
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@@ -409,6 +421,18 @@ public class KickCParserBaseListener implements KickCParserListener {
|
|||||||
* <p>The default implementation does nothing.</p>
|
* <p>The default implementation does nothing.</p>
|
||||||
*/
|
*/
|
||||||
@Override public void exitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx) { }
|
@Override public void exitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx) { }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>The default implementation does nothing.</p>
|
||||||
|
*/
|
||||||
|
@Override public void enterDirectiveCallingConvention(KickCParser.DirectiveCallingConventionContext ctx) { }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>The default implementation does nothing.</p>
|
||||||
|
*/
|
||||||
|
@Override public void exitDirectiveCallingConvention(KickCParser.DirectiveCallingConventionContext ctx) { }
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
|
@@ -181,6 +181,13 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
|||||||
* {@link #visitChildren} on {@code ctx}.</p>
|
* {@link #visitChildren} on {@code ctx}.</p>
|
||||||
*/
|
*/
|
||||||
@Override public T visitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx) { return visitChildren(ctx); }
|
@Override public T visitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx) { return visitChildren(ctx); }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>The default implementation returns the result of calling
|
||||||
|
* {@link #visitChildren} on {@code ctx}.</p>
|
||||||
|
*/
|
||||||
|
@Override public T visitGlobalDirectiveCalling(KickCParser.GlobalDirectiveCallingContext ctx) { return visitChildren(ctx); }
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
@@ -244,6 +251,13 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
|||||||
* {@link #visitChildren} on {@code ctx}.</p>
|
* {@link #visitChildren} on {@code ctx}.</p>
|
||||||
*/
|
*/
|
||||||
@Override public T visitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx) { return visitChildren(ctx); }
|
@Override public T visitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx) { return visitChildren(ctx); }
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>The default implementation returns the result of calling
|
||||||
|
* {@link #visitChildren} on {@code ctx}.</p>
|
||||||
|
*/
|
||||||
|
@Override public T visitDirectiveCallingConvention(KickCParser.DirectiveCallingConventionContext ctx) { return visitChildren(ctx); }
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
|
@@ -273,6 +273,18 @@ public interface KickCParserListener extends ParseTreeListener {
|
|||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
*/
|
*/
|
||||||
void exitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx);
|
void exitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx);
|
||||||
|
/**
|
||||||
|
* Enter a parse tree produced by the {@code globalDirectiveCalling}
|
||||||
|
* labeled alternative in {@link KickCParser#globalDirective}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void enterGlobalDirectiveCalling(KickCParser.GlobalDirectiveCallingContext ctx);
|
||||||
|
/**
|
||||||
|
* Exit a parse tree produced by the {@code globalDirectiveCalling}
|
||||||
|
* labeled alternative in {@link KickCParser#globalDirective}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void exitGlobalDirectiveCalling(KickCParser.GlobalDirectiveCallingContext ctx);
|
||||||
/**
|
/**
|
||||||
* Enter a parse tree produced by the {@code directiveConst}
|
* Enter a parse tree produced by the {@code directiveConst}
|
||||||
* labeled alternative in {@link KickCParser#directive}.
|
* labeled alternative in {@link KickCParser#directive}.
|
||||||
@@ -381,6 +393,18 @@ public interface KickCParserListener extends ParseTreeListener {
|
|||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
*/
|
*/
|
||||||
void exitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx);
|
void exitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx);
|
||||||
|
/**
|
||||||
|
* Enter a parse tree produced by the {@code directiveCallingConvention}
|
||||||
|
* labeled alternative in {@link KickCParser#directive}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void enterDirectiveCallingConvention(KickCParser.DirectiveCallingConventionContext ctx);
|
||||||
|
/**
|
||||||
|
* Exit a parse tree produced by the {@code directiveCallingConvention}
|
||||||
|
* labeled alternative in {@link KickCParser#directive}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
*/
|
||||||
|
void exitDirectiveCallingConvention(KickCParser.DirectiveCallingConventionContext ctx);
|
||||||
/**
|
/**
|
||||||
* Enter a parse tree produced by {@link KickCParser#stmtSeq}.
|
* Enter a parse tree produced by {@link KickCParser#stmtSeq}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
@@ -168,6 +168,13 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
|||||||
* @return the visitor result
|
* @return the visitor result
|
||||||
*/
|
*/
|
||||||
T visitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx);
|
T visitGlobalDirectiveEncoding(KickCParser.GlobalDirectiveEncodingContext ctx);
|
||||||
|
/**
|
||||||
|
* Visit a parse tree produced by the {@code globalDirectiveCalling}
|
||||||
|
* labeled alternative in {@link KickCParser#globalDirective}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
* @return the visitor result
|
||||||
|
*/
|
||||||
|
T visitGlobalDirectiveCalling(KickCParser.GlobalDirectiveCallingContext ctx);
|
||||||
/**
|
/**
|
||||||
* Visit a parse tree produced by the {@code directiveConst}
|
* Visit a parse tree produced by the {@code directiveConst}
|
||||||
* labeled alternative in {@link KickCParser#directive}.
|
* labeled alternative in {@link KickCParser#directive}.
|
||||||
@@ -231,6 +238,13 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
|||||||
* @return the visitor result
|
* @return the visitor result
|
||||||
*/
|
*/
|
||||||
T visitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx);
|
T visitDirectiveReserveZp(KickCParser.DirectiveReserveZpContext ctx);
|
||||||
|
/**
|
||||||
|
* Visit a parse tree produced by the {@code directiveCallingConvention}
|
||||||
|
* labeled alternative in {@link KickCParser#directive}.
|
||||||
|
* @param ctx the parse tree
|
||||||
|
* @return the visitor result
|
||||||
|
*/
|
||||||
|
T visitDirectiveCallingConvention(KickCParser.DirectiveCallingConventionContext ctx);
|
||||||
/**
|
/**
|
||||||
* Visit a parse tree produced by {@link KickCParser#stmtSeq}.
|
* Visit a parse tree produced by {@link KickCParser#stmtSeq}.
|
||||||
* @param ctx the parse tree
|
* @param ctx the parse tree
|
||||||
|
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.passes;
|
|||||||
import dk.camelot64.kickc.NumberParser;
|
import dk.camelot64.kickc.NumberParser;
|
||||||
import dk.camelot64.kickc.SourceLoader;
|
import dk.camelot64.kickc.SourceLoader;
|
||||||
import dk.camelot64.kickc.asm.AsmClobber;
|
import dk.camelot64.kickc.asm.AsmClobber;
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
|
|
||||||
import dk.camelot64.kickc.model.*;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.operators.*;
|
import dk.camelot64.kickc.model.operators.*;
|
||||||
import dk.camelot64.kickc.model.statements.*;
|
import dk.camelot64.kickc.model.statements.*;
|
||||||
@@ -159,6 +158,18 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The current calling convention for procedures. */
|
||||||
|
Procedure.CallingConvension currentCallingConvention = Procedure.CallingConvension.PHI_CALL;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitGlobalDirectiveCalling(KickCParser.GlobalDirectiveCallingContext ctx) {
|
||||||
|
Procedure.CallingConvension callingConvension = Procedure.CallingConvension.getCallingConvension(ctx.CALLINGCONVENTION().getText());
|
||||||
|
if(callingConvension!=null) {
|
||||||
|
currentCallingConvention = callingConvension;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/** The current code segment - if null the default segment is used. */
|
/** The current code segment - if null the default segment is used. */
|
||||||
String currentCodeSegment = Scope.SEGMENT_CODE_DEFAULT;
|
String currentCodeSegment = Scope.SEGMENT_CODE_DEFAULT;
|
||||||
|
|
||||||
@@ -183,7 +194,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
SymbolType type = declVarType;
|
SymbolType type = declVarType;
|
||||||
List<Directive> directives = declVarDirectives;
|
List<Directive> directives = declVarDirectives;
|
||||||
String name = ctx.NAME().getText();
|
String name = ctx.NAME().getText();
|
||||||
Procedure procedure = getCurrentScope().addProcedure(name, type, currentCodeSegment, currentDataSegment);
|
Procedure procedure = getCurrentScope().addProcedure(name, type, currentCodeSegment, currentDataSegment, currentCallingConvention);
|
||||||
addDirectives(procedure, directives, StatementSource.procedureBegin(ctx));
|
addDirectives(procedure, directives, StatementSource.procedureBegin(ctx));
|
||||||
procedure.setComments(ensureUnusedComments(getCommentsSymbol(ctx)));
|
procedure.setComments(ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||||
scopeStack.push(procedure);
|
scopeStack.push(procedure);
|
||||||
@@ -668,24 +679,24 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
lValue.setDeclaredExport(true);
|
lValue.setDeclaredExport(true);
|
||||||
} else if(directive instanceof DirectiveAlign) {
|
} else if(directive instanceof DirectiveAlign) {
|
||||||
if(type instanceof SymbolTypeArray || type.equals(SymbolType.STRING)) {
|
if(type instanceof SymbolTypeArray || type.equals(SymbolType.STRING)) {
|
||||||
lValue.setDeclaredAlignment(((DirectiveAlign) directive).getAlignment());
|
lValue.setDeclaredAlignment(((DirectiveAlign) directive).alignment);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Error! Cannot align variable that is not a string or an array " + lValue.toString(program), source);
|
throw new CompileError("Error! Cannot align variable that is not a string or an array " + lValue.toString(program), source);
|
||||||
}
|
}
|
||||||
} else if(directive instanceof DirectiveRegister) {
|
} else if(directive instanceof DirectiveRegister) {
|
||||||
DirectiveRegister directiveRegister = (DirectiveRegister) directive;
|
DirectiveRegister directiveRegister = (DirectiveRegister) directive;
|
||||||
if(directiveRegister.getName() != null) {
|
if(directiveRegister.name != null) {
|
||||||
// Ignore register directive without parameter (all variables are placed on ZP and attempted register uplift anyways)
|
// Ignore register directive without parameter (all variables are placed on ZP and attempted register uplift anyways)
|
||||||
Registers.Register register = Registers.getRegister(directiveRegister.getName());
|
Registers.Register register = Registers.getRegister(directiveRegister.name);
|
||||||
if(register == null) {
|
if(register == null) {
|
||||||
throw new CompileError("Error! Unknown register " + directiveRegister.getName(), source);
|
throw new CompileError("Error! Unknown register " + directiveRegister.name, source);
|
||||||
}
|
}
|
||||||
lValue.setDeclaredRegister(register);
|
lValue.setDeclaredRegister(register);
|
||||||
} else if(directiveRegister.getAddress() != null) {
|
} else if(directiveRegister.address != null) {
|
||||||
// Allocate to specific address
|
// Allocate to specific address
|
||||||
Long address = ((DirectiveRegister) directive).address;
|
Long address = ((DirectiveRegister) directive).address;
|
||||||
if(address>255) {
|
if(address>255) {
|
||||||
throw new CompileError("Error! Register not on zeropage " + directiveRegister.getAddress(), source);
|
throw new CompileError("Error! Register not on zeropage " + directiveRegister.address, source);
|
||||||
}
|
}
|
||||||
Registers.Register register = new Registers.RegisterZpDeclared(address.intValue());
|
Registers.Register register = new Registers.RegisterZpDeclared(address.intValue());
|
||||||
lValue.setDeclaredRegister(register);
|
lValue.setDeclaredRegister(register);
|
||||||
@@ -720,10 +731,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
for(Directive directive : directives) {
|
for(Directive directive : directives) {
|
||||||
if(directive instanceof DirectiveInline) {
|
if(directive instanceof DirectiveInline) {
|
||||||
procedure.setDeclaredInline(true);
|
procedure.setDeclaredInline(true);
|
||||||
|
} else if(directive instanceof DirectiveCallingConvention) {
|
||||||
|
procedure.setCallingConvension(((DirectiveCallingConvention) directive).callingConvension);
|
||||||
} else if(directive instanceof DirectiveInterrupt) {
|
} else if(directive instanceof DirectiveInterrupt) {
|
||||||
procedure.setInterruptType(((DirectiveInterrupt) directive).interruptType);
|
procedure.setInterruptType(((DirectiveInterrupt) directive).interruptType);
|
||||||
} else if(directive instanceof DirectiveReserveZp) {
|
} else if(directive instanceof DirectiveReserveZp) {
|
||||||
procedure.setReservedZps(((DirectiveReserveZp) directive).getReservedZp());
|
procedure.setReservedZps(((DirectiveReserveZp) directive).reservedZp);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Unsupported function directive " + directive, source);
|
throw new CompileError("Unsupported function directive " + directive, source);
|
||||||
}
|
}
|
||||||
@@ -771,6 +784,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
return new DirectiveInterrupt(type);
|
return new DirectiveInterrupt(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Directive visitDirectiveCallingConvention(KickCParser.DirectiveCallingConventionContext ctx) {
|
||||||
|
Procedure.CallingConvension callingConvension = Procedure.CallingConvension.getCallingConvension(ctx.getText());
|
||||||
|
return new DirectiveCallingConvention(callingConvension);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Directive visitDirectiveAlign(KickCParser.DirectiveAlignContext ctx) {
|
public Directive visitDirectiveAlign(KickCParser.DirectiveAlignContext ctx) {
|
||||||
Number alignment = NumberParser.parseLiteral(ctx.NUMBER().getText());
|
Number alignment = NumberParser.parseLiteral(ctx.NUMBER().getText());
|
||||||
@@ -2136,6 +2155,16 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
private static class DirectiveConst implements Directive {
|
private static class DirectiveConst implements Directive {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Function with specific declared calling convention. */
|
||||||
|
private static class DirectiveCallingConvention implements Directive {
|
||||||
|
Procedure.CallingConvension callingConvension;
|
||||||
|
|
||||||
|
public DirectiveCallingConvention(Procedure.CallingConvension callingConvension) {
|
||||||
|
this.callingConvension = callingConvension;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** Function declared inline. */
|
/** Function declared inline. */
|
||||||
private static class DirectiveInline implements Directive {
|
private static class DirectiveInline implements Directive {
|
||||||
}
|
}
|
||||||
@@ -2165,9 +2194,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
this.alignment = alignment;
|
this.alignment = alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAlignment() {
|
|
||||||
return alignment;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Variable register allocation. */
|
/** Variable register allocation. */
|
||||||
@@ -2185,13 +2211,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
this.address = address;
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getAddress() {
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reservation of zero-page addresses */
|
/** Reservation of zero-page addresses */
|
||||||
@@ -2202,10 +2221,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
this.reservedZp = reservedZp;
|
this.reservedZp = reservedZp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Integer> getReservedZp() {
|
|
||||||
return reservedZp;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ import dk.camelot64.kickc.model.values.*;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/** Pass that modifies a control flow graph to call procedures by passing parameters through registers */
|
/** Pass that modifies a control flow graph to call {@link dk.camelot64.kickc.model.symbols.Procedure.CallingConvension#PHI_CALL} procedures by passing parameters through registers */
|
||||||
public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||||
|
|
||||||
private Program program;
|
private Program program;
|
||||||
@@ -49,10 +49,16 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StatementCall visitCall(StatementCall origCall) {
|
public StatementCall visitCall(StatementCall origCall) {
|
||||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
|
||||||
// Generate parameter passing assignments
|
// Generate parameter passing assignments
|
||||||
ProcedureRef procedureRef = origCall.getProcedure();
|
ProcedureRef procedureRef = origCall.getProcedure();
|
||||||
Procedure procedure = getScope().getProcedure(procedureRef);
|
Procedure procedure = getScope().getProcedure(procedureRef);
|
||||||
|
// If not PHI-call - skip
|
||||||
|
if(!Procedure.CallingConvension.PHI_CALL.equals(procedure.getCallingConvension())) {
|
||||||
|
StatementCall copyCall = super.visitCall(origCall);
|
||||||
|
copyCall.setProcedure(procedureRef);
|
||||||
|
return copyCall;
|
||||||
|
}
|
||||||
|
|
||||||
List<Variable> parameterDecls = procedure.getParameters();
|
List<Variable> parameterDecls = procedure.getParameters();
|
||||||
List<RValue> parameterValues = origCall.getParameters();
|
List<RValue> parameterValues = origCall.getParameters();
|
||||||
if(parameterDecls.size()!=parameterValues.size()) {
|
if(parameterDecls.size()!=parameterValues.size()) {
|
||||||
@@ -120,6 +126,10 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
|||||||
ControlFlowBlock currentBlock = getCurrentBlock();
|
ControlFlowBlock currentBlock = getCurrentBlock();
|
||||||
String currentProcName = currentBlock.getLabel().getScopeNames();
|
String currentProcName = currentBlock.getLabel().getScopeNames();
|
||||||
Procedure procedure = program.getScope().getProcedure(currentProcName);
|
Procedure procedure = program.getScope().getProcedure(currentProcName);
|
||||||
|
// If not PHI-call - skip
|
||||||
|
if(!Procedure.CallingConvension.PHI_CALL.equals(procedure.getCallingConvension()))
|
||||||
|
return super.visitReturn(orig);
|
||||||
|
|
||||||
// Add self-assignments for all variables modified in the procedure
|
// Add self-assignments for all variables modified in the procedure
|
||||||
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
|
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
|
||||||
for(VariableRef modifiedVar : modifiedVars) {
|
for(VariableRef modifiedVar : modifiedVars) {
|
||||||
|
@@ -12,7 +12,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass that modifies a control flow graph to call procedures by passing return value through registers
|
* Pass that modifies a control flow graph to call procedures by passing return value through registers for {@link dk.camelot64.kickc.model.symbols.Procedure.CallingConvension#PHI_CALL}
|
||||||
*/
|
*/
|
||||||
public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor {
|
public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor {
|
||||||
|
|
||||||
@@ -33,6 +33,13 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
|
|||||||
// Generate return value assignment
|
// Generate return value assignment
|
||||||
ProcedureRef procedureRef = origCall.getProcedure();
|
ProcedureRef procedureRef = origCall.getProcedure();
|
||||||
Procedure procedure = program.getScope().getProcedure(procedureRef);
|
Procedure procedure = program.getScope().getProcedure(procedureRef);
|
||||||
|
// If not PHI-call - skip
|
||||||
|
if(!Procedure.CallingConvension.PHI_CALL.equals(procedure.getCallingConvension())) {
|
||||||
|
StatementCall copyCall = super.visitCall(origCall);
|
||||||
|
copyCall.setProcedure(procedureRef);
|
||||||
|
return copyCall;
|
||||||
|
}
|
||||||
|
|
||||||
String procedureName = origCall.getProcedureName();
|
String procedureName = origCall.getProcedureName();
|
||||||
StatementCall copyCall = new StatementCall(null, procedureName, null, origCall.getSource(), origCall.getComments());
|
StatementCall copyCall = new StatementCall(null, procedureName, null, origCall.getSource(), origCall.getComments());
|
||||||
copyCall.setProcedure(procedureRef);
|
copyCall.setProcedure(procedureRef);
|
||||||
@@ -106,6 +113,13 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StatementReturn visitReturn(StatementReturn orig) {
|
public StatementReturn visitReturn(StatementReturn orig) {
|
||||||
|
ControlFlowBlock currentBlock = getCurrentBlock();
|
||||||
|
String currentProcName = currentBlock.getLabel().getScopeNames();
|
||||||
|
Procedure procedure = program.getScope().getProcedure(currentProcName);
|
||||||
|
// If not PHI-call - skip
|
||||||
|
if(!Procedure.CallingConvension.PHI_CALL.equals(procedure.getCallingConvension()))
|
||||||
|
return super.visitReturn(orig);
|
||||||
|
|
||||||
addStatementToCurrentBlock(new StatementReturn(null, orig.getSource(), orig.getComments()));
|
addStatementToCurrentBlock(new StatementReturn(null, orig.getSource(), orig.getComments()));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,18 @@ public class TestPrograms {
|
|||||||
public TestPrograms() {
|
public TestPrograms() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@Test
|
||||||
|
public void testProcedureCallingConventionStack1() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("procedure-callingconvention-stack-1", log());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcedureCallingConventionStack0() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("procedure-callingconvention-stack-0", log());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStringPointerProblem() throws IOException, URISyntaxException {
|
public void testStringPointerProblem() throws IOException, URISyntaxException {
|
||||||
compileAndCompare("string-pointer-problem");
|
compileAndCompare("string-pointer-problem");
|
||||||
|
11
src/test/kc/procedure-callingconvention-stack-0.kc
Normal file
11
src/test/kc/procedure-callingconvention-stack-0.kc
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Test a procedure with calling convention stack
|
||||||
|
|
||||||
|
const char* SCREEN = 0x0400;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
SCREEN[0] = plus('0', 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
char __stackcall plus(char a, char b) {
|
||||||
|
return a+b;
|
||||||
|
}
|
13
src/test/kc/procedure-callingconvention-stack-1.kc
Normal file
13
src/test/kc/procedure-callingconvention-stack-1.kc
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Test a procedure with calling convention stack
|
||||||
|
|
||||||
|
const char* SCREEN = 0x0400;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
SCREEN[0] = plus('0', 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma calling(__stackcall)
|
||||||
|
|
||||||
|
char plus(char a, char b) {
|
||||||
|
return a+b;
|
||||||
|
}
|
Reference in New Issue
Block a user