1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-27 21:57:28 +00:00

Fixed tests. Moved all attributes to SymbolVariable.

This commit is contained in:
jespergravgaard 2019-10-31 23:07:51 +01:00
parent 79d4f6f1a5
commit e35f1b1530
12 changed files with 71 additions and 124 deletions

View File

@ -3,10 +3,7 @@ package dk.camelot64.kickc.asm;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.*;
import dk.camelot64.kickc.model.symbols.ConstantVar;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Symbol;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
@ -311,19 +308,7 @@ public class AsmFormat {
* @param boundVar The variable
* @return The ASM parameter to use in the ASM code
*/
public static String getAsmParamName(Variable boundVar, ScopeRef codeScopeRef) {
ScopeRef varScopeRef = boundVar.getScope().getRef();
String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
return getAsmParamName(varScopeRef, asmName, codeScopeRef);
}
/**
* Get the ASM parameter for a specific bound constant
*
* @param boundVar The constant
* @return The ASM parameter to use in the ASM code
*/
public static String getAsmParamName(ConstantVar boundVar, ScopeRef codeScopeRef) {
public static String getAsmParamName(SymbolVariable boundVar, ScopeRef codeScopeRef) {
ScopeRef varScopeRef = boundVar.getScope().getRef();
String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
return getAsmParamName(varScopeRef, asmName, codeScopeRef);

View File

@ -1,6 +1,5 @@
package dk.camelot64.kickc.model.symbols;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.ConstantRef;
import dk.camelot64.kickc.model.values.ConstantValue;
@ -18,20 +17,4 @@ public class ConstantVar extends SymbolVariable {
return new ConstantRef(this);
}
@Override
public String toString(Program program) {
String s = new StringBuilder()
.append("(")
.append("const" + " ")
.append(getType().getTypeName())
.append(") ")
.append(getFullName()).toString();
return s;
}
@Override
public String toString() {
return toString(null);
}
}

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.model.symbols;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.Registers;
import dk.camelot64.kickc.model.types.SymbolType;
@ -21,7 +22,7 @@ public abstract class SymbolVariable implements Symbol {
/** The type of the variable. VAR means tha type is unknown, and has not been inferred yet. */
private SymbolType type;
/** true if the symbol type is infered (not declared) */
/** true if the symbol type is inferred (not declared) */
private boolean inferredType;
/** A short name used for the variable in ASM code. If possible variable names of variables are shortened in ASM code. This is possible, when several versions of the var use the same register. */
@ -56,7 +57,8 @@ public abstract class SymbolVariable implements Symbol {
/** Specifies that the variable must live in memory. */
private boolean declaredAsNotRegister;
/** Strategy being used for storing and accessing the variable. The value depends on the directives memory/register/volatile/const - and on the compilers optimization decisions.
/**
* Strategy being used for storing and accessing the variable. The value depends on the directives memory/register/volatile/const - and on the compilers optimization decisions.
* <ul>
* <li>PHI variables are turned into versions and PHI-nodes are used for them throughout the entire program. They cannot be "volatile" and the "address-of" operator cannot be used on them.</li>
* <li>INTERMEDIATE variables are created when expressions are broken into smaller statements. </li>
@ -64,13 +66,17 @@ public abstract class SymbolVariable implements Symbol {
* <li>CONSTANT variables are constant.
* </ul>
**/
public enum StorageStrategy { PHI_MASTER, PHI_VERSION, INTERMEDIATE, LOAD_STORE, CONSTANT }
public enum StorageStrategy {
PHI_MASTER, PHI_VERSION, INTERMEDIATE, LOAD_STORE, CONSTANT
}
/** The storage strategy for the variable. */
private StorageStrategy storageStrategy;
/** Memory area used for storing the variable (if is is stored in memory). */
public enum MemoryArea { ZEROPAGE_MEMORY, MAIN_MEMORY }
public enum MemoryArea {
ZEROPAGE_MEMORY, MAIN_MEMORY
}
/** The memory area where the variable lives (if stored in memory). */
private MemoryArea memoryArea;
@ -87,6 +93,12 @@ public abstract class SymbolVariable implements Symbol {
/** The constant value if the variable is a constant. Null otherwise. */
private ConstantValue constantValue;
/** The number of the next version (only used for PHI masters) */
private Integer nextPhiVersionNumber;
/** If the variable is assigned to a specific "register", this contains the register. If null the variable has no allocation (yet). Constants are never assigned to registers. */
private Registers.Register allocation;
public SymbolVariable(String name, Scope scope, SymbolType type, StorageStrategy storageStrategy, MemoryArea memoryArea, String dataSegment) {
this.name = name;
this.scope = scope;
@ -98,6 +110,9 @@ public abstract class SymbolVariable implements Symbol {
this.memoryArea = memoryArea;
this.constantDeclaration = ConstantDeclaration.MAYBE_CONST;
setFullName();
if(isStoragePhiMaster())
this.nextPhiVersionNumber = 0;
}
private void setFullName() {
@ -105,6 +120,41 @@ public abstract class SymbolVariable implements Symbol {
fullName = (scopeName.length() > 0) ? scopeName + "::" + name : name;
}
/**
* Creates a new PHI-version from a PHI-master
*
* @return The new version of the PHI master
*/
public Variable createVersion() {
if(!isStoragePhiMaster())
throw new InternalError("Cannot version non-PHI variable " + this.toString());
Variable version = new Variable(this, nextPhiVersionNumber++);
getScope().add(version);
return version;
}
/**
* If the variable is a version of a variable returns the original variable.
*
* @return The original variable. Null if this is not a version.
*/
public Variable getVersionOf() {
if(!isStoragePhiVersion())
throw new InternalError("Cannot get master for non-PHI version variable " + this.toString());
String name = getName();
String versionOfName = name.substring(0, name.indexOf("#"));
return getScope().getVariable(versionOfName);
}
public Registers.Register getAllocation() {
return allocation;
}
public void setAllocation(Registers.Register allocation) {
this.allocation = allocation;
}
public ConstantValue getConstantValue() {
return constantValue;
}
@ -318,13 +368,13 @@ public abstract class SymbolVariable implements Symbol {
@Override
public String toString(Program program) {
String s = new StringBuilder()
return new StringBuilder()
.append("(")
.append(type.getTypeName())
.append(inferredType ? "~" : "")
.append((constantValue != null) ? "const " : "")
.append(getType().getTypeName())
.append((constantValue==null&&inferredType) ? "~" : "")
.append(") ")
.append(getFullName()).toString();
return s;
}
@Override

View File

@ -1,34 +1,15 @@
package dk.camelot64.kickc.model.symbols;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Registers;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.Objects;
/**
* A Variable in the program.
* <p>
* There are several types of variables
* <p>
* - Intermediate: A variable added by the compiler to hold some intermediate value. Intermediate variables are names $1, $2, ...
* - PHI-variable: A variable with storage strategy PHI is turned into versions. The variable itself is never used directly in the program.
* - PHI-versions: A variable with storage strategy PHI is turned into versions. Versions of the PHI-variable name are named name#1, name#2, name#3
* - Memory: A variable with storage strategy memory is used directly in the program.
*/
public class Variable extends SymbolVariable {
/** The number of the next version (only used for PHI masters) */
private Integer nextPhiVersionNumber;
/** If the variable is assigned to a specific "register", this contains the register. If null the variable has no allocation (yet). Constants are never assigned to registers. */
private Registers.Register allocation;
public Variable(String name, Scope scope, SymbolType type, String dataSegment, StorageStrategy storageStrategy, MemoryArea memoryArea) {
super(name, scope, type, storageStrategy, memoryArea, dataSegment);
if(isStoragePhiMaster())
this.nextPhiVersionNumber = 0;
}
/**
@ -37,7 +18,7 @@ public class Variable extends SymbolVariable {
* @param phiMaster The PHI master variable.
* @param version The version number
*/
public Variable(Variable phiMaster, int version) {
public Variable(SymbolVariable phiMaster, int version) {
super(phiMaster.getName() + "#" + version, phiMaster.getScope(), phiMaster.getType(), StorageStrategy.PHI_VERSION, phiMaster.getMemoryArea(), phiMaster.getDataSegment());
this.setDeclaredAlignment(phiMaster.getDeclaredAlignment());
this.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister());
@ -55,53 +36,4 @@ public class Variable extends SymbolVariable {
return new VariableRef(this);
}
public Registers.Register getAllocation() {
return allocation;
}
public void setAllocation(Registers.Register allocation) {
this.allocation = allocation;
}
/**
* Creates a new PHI-version from a PHI-master
*
* @return The new version of the PHI master
*/
public Variable createVersion() {
if(!isStoragePhiMaster())
throw new InternalError("Cannot version non-PHI variable " + this.toString());
Variable version = new Variable(this, nextPhiVersionNumber++);
getScope().add(version);
return version;
}
/**
* If the variable is a version of a variable returns the original variable.
*
* @return The original variable. Null if this is not a version.
*/
public Variable getVersionOf() {
if(!isStoragePhiVersion())
throw new InternalError("Cannot get master for non-PHI version variable " + this.toString());
String name = getName();
String versionOfName = name.substring(0, name.indexOf("#"));
return getScope().getVariable(versionOfName);
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
if(o == null || getClass() != o.getClass()) return false;
if(!super.equals(o)) return false;
Variable variable = (Variable) o;
return Objects.equals(allocation, variable.allocation);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), allocation);
}
}

View File

@ -293,7 +293,6 @@ sgn_u16: {
__b1:
lda #<-1
sta.z return
lda #>-1
sta.z return+1
rts
}

View File

@ -4279,6 +4279,7 @@ Removing instruction lda #>0
Removing instruction lda.z e+1
Removing instruction lda.z e1+1
Removing instruction ldy #0
Removing instruction lda #>-1
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Replacing label __b5_from___b4 with __b2
@ -4617,7 +4618,7 @@ reg byte a [ bitmap_init::$6 ]
FINAL ASSEMBLER
Score: 30190
Score: 30188
// File Comments
// Shows that bitmap2.kc line() does not have the same problem as bitmap-draw.kc
@ -5128,7 +5129,6 @@ sgn_u16: {
// [78] phi (word) sgn_u16::return#4 = (byte) -1 [phi:sgn_u16::@1->sgn_u16::@return#0] -- vwuz1=vbuc1
lda #<-1
sta.z return
lda #>-1
sta.z return+1
// sgn_u16::@return
// }

View File

@ -316,7 +316,6 @@ sgn_u16: {
__b1:
lda #<-1
sta.z return
lda #>-1
sta.z return+1
rts
}

View File

@ -4626,6 +4626,7 @@ Removing instruction ldy.z a
Removing instruction lda.z e+1
Removing instruction lda.z e1+1
Removing instruction ldy #0
Removing instruction lda #>-1
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Replacing label __b7_from___b16 with __b7
@ -4974,7 +4975,7 @@ reg byte a [ bitmap_init::$6 ]
FINAL ASSEMBLER
Score: 27289
Score: 27287
// File Comments
// Tests the simple bitmap plotter
@ -5513,7 +5514,6 @@ sgn_u16: {
// [86] phi (word) sgn_u16::return#4 = (byte) -1 [phi:sgn_u16::@1->sgn_u16::@return#0] -- vwuz1=vbuc1
lda #<-1
sta.z return
lda #>-1
sta.z return+1
// sgn_u16::@return
// }

View File

@ -505,7 +505,6 @@ sgn_u16: {
__b1:
lda #<-1
sta.z return
lda #>-1
sta.z return+1
rts
}

View File

@ -12004,6 +12004,7 @@ Removing instruction lda #0
Removing instruction lda.z e+1
Removing instruction lda.z e1+1
Removing instruction ldy #0
Removing instruction lda #>-1
Replacing instruction lda #<0 with TXA
Removing instruction lda #>0
Removing instruction lda #0
@ -12199,7 +12200,7 @@ Removing instruction __breturn:
Removing instruction b1:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Fixing long branch [770] bne __b1 to beq
Fixing long branch [769] bne __b1 to beq
Fixing long branch [308] beq __b4 to bne
FINAL SYMBOL TABLE
@ -12790,7 +12791,7 @@ reg byte a [ mulf_init::$13 ]
FINAL ASSEMBLER
Score: 678158
Score: 678156
// File Comments
// Show a few simple splines using the splines library
@ -13681,7 +13682,6 @@ sgn_u16: {
// [164] phi (word) sgn_u16::return#4 = (byte) -1 [phi:sgn_u16::@1->sgn_u16::@return#0] -- vwuz1=vbuc1
lda #<-1
sta.z return
lda #>-1
sta.z return+1
// sgn_u16::@return
// }

View File

@ -13,7 +13,6 @@ main: {
beq __b3
lda #<-1
sta.z w
lda #>-1
sta.z w+1
jmp __b2
__b3:

View File

@ -419,6 +419,8 @@ Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #>-1
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Replacing label __b1_from___b2 with __b1
Removing instruction __bbegin:
@ -467,7 +469,7 @@ reg byte a [ main::$3 ]
FINAL ASSEMBLER
Score: 626
Score: 606
// File Comments
// Problem with assigning negative word constant (vwuz1=vbuc1)
@ -506,7 +508,6 @@ main: {
// [9] phi (word) main::w#2 = (byte) -1 [phi:main::@1->main::@2#0] -- vwuz1=vbuc1
lda #<-1
sta.z w
lda #>-1
sta.z w+1
jmp __b2
// main::@3