1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-24 16:30:54 +00:00

Updated to ANTLR4.9. Merged Andrzej Śliwa implementation of __address() support for constant expressions branch address_with_expression_value. Closes !1

This commit is contained in:
jespergravgaard 2020-12-11 01:18:36 +01:00
commit 82a045934d
27 changed files with 1927 additions and 614 deletions

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: org.antlr:antlr4:4.8-1">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.8-1/antlr4-4.8-1.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.8-1/antlr4-4.8-1-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.8-1/antlr4-4.8-1-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="Maven: org.antlr:antlr4:4.9">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9/antlr4-4.9.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9/antlr4-4.9-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.9/antlr4-4.9-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,13 +1,13 @@
<component name="libraryTable">
<library name="Maven: org.antlr:antlr4-runtime:4.8-1">
<library name="Maven: org.antlr:antlr4-runtime:4.9">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.8-1/antlr4-runtime-4.8-1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9/antlr4-runtime-4.9.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.8-1/antlr4-runtime-4.8-1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9/antlr4-runtime-4.9-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.8-1/antlr4-runtime-4.8-1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.9/antlr4-runtime-4.9-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -11,11 +11,11 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:antlr4:4.8-1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:antlr4:4.9" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.antlr:ST4:4.3" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.abego.treelayout:org.abego.treelayout.core:1.0.3" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.ibm.icu:icu4j:61.1" level="project" />
<orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.8-1" level="project" />
<orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.9" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.6.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.6.2" level="project" />

View File

@ -27,13 +27,13 @@
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.8-1</version>
<version>4.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.8-1</version>
<version>4.9</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.ConstantValue;
import java.util.List;
@ -138,12 +139,16 @@ public class Directive {
/** Variable hardcoded __address() directive */
public static class Address extends Directive {
/** Optional hard-coded address to use for storing the variable. */
public Long address;
/** Expression for calculating the address. */
public ConstantValue addressValue;
public Address(Long address) {
/** Optional hard-coded address to use for storing the variable. */
public Long addressLiteral;
public Address(ConstantValue addressValue, Long addressLiteral) {
super("__address");
this.address = address;
this.addressValue = addressValue;
this.addressLiteral = addressLiteral;
}
}

View File

@ -5,6 +5,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.ScopeRef;
import java.util.List;
@ -322,7 +323,7 @@ public class VariableBuilder {
return Variable.MemoryArea.MAIN_MEMORY;
Directive.Address addressDirective = findDirective(Directive.Address.class, directives);
if(addressDirective != null)
return (addressDirective.address < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY;
return (addressDirective.addressLiteral < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY;
else if(!isConstant() && isOptimize())
return Variable.MemoryArea.ZEROPAGE_MEMORY;
else {
@ -359,11 +360,11 @@ public class VariableBuilder {
*
* @return The memory alignment
*/
public Long getAddress() {
public ConstantValue getAddress() {
Directive.Address addressDirective = findDirective(Directive.Address.class, directives);
if(addressDirective != null) {
if(isArray()) {
return addressDirective.address;
return addressDirective.addressValue;
}
}
return null;
@ -382,12 +383,12 @@ public class VariableBuilder {
Directive.Address addressDirective = findDirective(Directive.Address.class, directives);
if(addressDirective != null) {
Variable.MemoryArea memoryArea = (addressDirective.address < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY;
Variable.MemoryArea memoryArea = (addressDirective.addressLiteral < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY;
if(Variable.MemoryArea.ZEROPAGE_MEMORY.equals(memoryArea)) {
return new Registers.RegisterZpMem(addressDirective.address.intValue(), -1, true);
return new Registers.RegisterZpMem(addressDirective.addressLiteral.intValue(), -1, true);
} else {
// TODO: Fix VariableRef for the hard-coded register
return new Registers.RegisterMainMem(null, -1, addressDirective.address);
return new Registers.RegisterMainMem(null, -1, addressDirective.addressLiteral);
}
}

View File

@ -651,6 +651,26 @@ public interface ProgramValue {
}
/** The memory address of a variable. */
class ProgramValueMemoryAddress implements ProgramValue {
private final Variable constantVar;
ProgramValueMemoryAddress(Variable constantVar) {
this.constantVar = constantVar;
}
@Override
public Value get() {
return constantVar.getMemoryAddress();
}
@Override
public void set(Value val) {
constantVar.setMemoryAddress((ConstantValue) val);
}
}
/** Bytes inside inline kickasm code. */
class ProgramValueKickAsmBytes implements ProgramValue {

View File

@ -58,6 +58,9 @@ public class ProgramValueIterator {
if(variable.isArray()) {
execute(new ProgramValue.ProgramValueArraySize(variable), programValueHandler, null, null, null);
}
if(variable.getMemoryAddress() != null) {
execute(new ProgramValue.ProgramValueMemoryAddress(variable), programValueHandler, null, null, null);
}
}
/**

View File

@ -95,7 +95,7 @@ public class Variable implements Symbol {
private Integer memoryAlignment;
/** Specifies that the variable must be placed at an absolute address in memory. Only allowed for arrays & strings. [Only Variables in memory and arrays] */
private Long memoryAddress;
private ConstantValue memoryAddress;
/** The data segment to put the variable into (if it is allocated in memory). [Only variables stored in memory and arrays] */
private String dataSegment;
@ -582,11 +582,11 @@ public class Variable implements Symbol {
this.memoryAlignment = memoryAlignment;
}
public Long getMemoryAddress() {
public ConstantValue getMemoryAddress() {
return memoryAddress;
}
public void setMemoryAddress(Long memoryAddress) {
public void setMemoryAddress(ConstantValue memoryAddress) {
this.memoryAddress = memoryAddress;
}

View File

@ -1,4 +1,4 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCLexer.g4 by ANTLR 4.8
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCLexer.g4 by ANTLR 4.9
package dk.camelot64.kickc.parser;
@ -13,7 +13,7 @@ import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class KickCLexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.8", RuntimeMetaData.VERSION); }
static { RuntimeMetaData.checkVersion("4.9", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =

View File

@ -151,7 +151,7 @@ directive
| REGISTER ( PAR_BEGIN ( NAME ) PAR_END)? #directiveRegister
| ADDRESS_ZEROPAGE #directiveMemoryAreaZp
| ADDRESS_MAINMEM #directiveMemoryAreaMain
| ADDRESS PAR_BEGIN ( NUMBER ) PAR_END #directiveMemoryAreaAddress
| ADDRESS PAR_BEGIN ( expr ) PAR_END #directiveMemoryAreaAddress
| VOLATILE #directiveVolatile
| STATIC #directiveStatic
| FORM_SSA #directiveFormSsa

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.8
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.9
package dk.camelot64.kickc.parser;

View File

@ -1,4 +1,4 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.8
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.9
package dk.camelot64.kickc.parser;

View File

@ -1,4 +1,4 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.8
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.9
package dk.camelot64.kickc.parser;

View File

@ -1,4 +1,4 @@
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.8
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickCParser.g4 by ANTLR 4.9
package dk.camelot64.kickc.parser;

View File

@ -1261,9 +1261,18 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
@Override
public Directive visitDirectiveMemoryAreaAddress(KickCParser.DirectiveMemoryAreaAddressContext ctx) {
try {
ConstantInteger memoryAddress = NumberParser.parseIntegerLiteral(ctx.NUMBER().getText());
Long address = memoryAddress.getInteger();
return new Directive.Address(address);
KickCParser.ExprContext initializer = ctx.expr();
RValue initValue = (initializer == null) ? null : (RValue) visit(initializer);
StatementSource statementSource = new StatementSource(ctx);
ConstantValue addressAsConstantValue = getConstInitValue(initValue, initializer, statementSource);
ConstantLiteral literal = addressAsConstantValue.calculateLiteral(program.getScope());
if(literal instanceof ConstantInteger) {
Long address = ((ConstantInteger) literal).getValue();
return new Directive.Address(addressAsConstantValue, address);
} else {
throw new CompileError("__address is not an integer :" + initValue.toString(program), new StatementSource(ctx));
}
} catch(NumberFormatException e) {
throw new CompileError(e.getMessage(), new StatementSource(ctx));
}

View File

@ -500,7 +500,7 @@ public class Pass4CodeGeneration {
// Set segment
setCurrentSegment(constantVar.getDataSegment(), asm);
// Set absolute address
asm.addLine(new AsmSetPc(asmName, AsmFormat.getAsmNumber(constantVar.getMemoryAddress())));
asm.addLine(new AsmSetPc(asmName, AsmFormat.getAsmConstant(program, constantVar.getMemoryAddress(), 99, scopeRef)));
// Add any comments
generateComments(asm, constantVar.getComments());
// Add any alignment

View File

@ -1069,6 +1069,11 @@ public class TestPrograms {
compileAndCompare("address-9.c");
}
@Test
public void testAddressWithExpressionValue() throws IOException, URISyntaxException {
compileAndCompare("address-with-expression-value.c");
}
@Test
public void testAddress8() throws IOException, URISyntaxException {
compileAndCompare("address-8.c");
@ -5061,8 +5066,8 @@ public class TestPrograms {
success &= helper.testOutput(baseFileName, ".cfg", program.getGraph().toString(program));
success &= helper.testOutput(baseFileName, ".log", program.getLog().toString());
if(!success) {
//System.out.println("\nCOMPILE LOG");
//System.out.println(program.getLog().toString());
// System.out.println("\nCOMPILE LOG");
// System.out.println(program.getLog().toString());
fail("Output does not match reference!");
}
// Save the ASM fragment caches (if there are any changes)

View File

@ -0,0 +1,16 @@
// Test declaring an address as expression
// The screen
char * const SCREEN = 0x0400;
word const var1 = 0x800;
word const var2 = 0x900;
// Data to be put on the screen
char __address(var1 + var2) DATA[1000];
void main() {
SCREEN[0] = DATA[0];
}

View File

@ -0,0 +1,18 @@
// Test declaring an address as expression
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const var1 = $800
.const var2 = $900
// The screen
.label SCREEN = $400
main: {
// SCREEN[0] = DATA[0]
lda DATA
sta SCREEN
// }
rts
}
.pc = var1+var2 "DATA"
// Data to be put on the screen
DATA: .fill $3e8, 0

View File

@ -0,0 +1,9 @@
void main()
main: scope:[main] from
[0] *SCREEN = *DATA
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

View File

@ -0,0 +1,151 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
SCREEN[0] = DATA[0]
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
const byte* DATA[$3e8] = { fill( $3e8, 0) }
const nomodify byte* SCREEN = (byte*)$400
void __start()
void main()
const nomodify word var1 = $800
const nomodify word var2 = $900
Adding number conversion cast (unumber) 0 in SCREEN[0] = DATA[0]
Adding number conversion cast (unumber) 0 in SCREEN[0] = DATA[(unumber)0]
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type 0
Finalized unsigned number type 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero DATA in [0] SCREEN[0] = DATA[0]
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = *DATA
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] *SCREEN = *DATA
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
void main()
Initial phi equivalence classes
Complete equivalence classes
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *SCREEN = *DATA [ ] ( [ ] { } ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 17 combination
Uplifting [] best 17 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test declaring an address as expression
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const var1 = $800
.const var2 = $900
// The screen
.label SCREEN = $400
// main
main: {
// [0] *SCREEN = *DATA -- _deref_pbuc1=_deref_pbuc2
lda DATA
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.pc = var1+var2 "DATA"
// Data to be put on the screen
DATA: .fill $3e8, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
const byte* DATA[$3e8] = { fill( $3e8, 0) }
const nomodify byte* SCREEN = (byte*) 1024
void main()
const nomodify word var1 = $800
const nomodify word var2 = $900
FINAL ASSEMBLER
Score: 14
// File Comments
// Test declaring an address as expression
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const var1 = $800
.const var2 = $900
// The screen
.label SCREEN = $400
// main
main: {
// SCREEN[0] = DATA[0]
// [0] *SCREEN = *DATA -- _deref_pbuc1=_deref_pbuc2
lda DATA
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.pc = var1+var2 "DATA"
// Data to be put on the screen
DATA: .fill $3e8, 0

View File

@ -0,0 +1,6 @@
const byte* DATA[$3e8] = { fill( $3e8, 0) }
const nomodify byte* SCREEN = (byte*) 1024
void main()
const nomodify word var1 = $800
const nomodify word var2 = $900