1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-26 19:30:00 +00:00

Added a memory area attribute to variables.

This commit is contained in:
jespergravgaard 2019-10-13 13:46:01 +02:00
parent f2660a8680
commit c231a1abe4
13 changed files with 75 additions and 37 deletions

View File

@ -80,12 +80,12 @@ public class AsmFragmentTemplate {
ProgramScope scope = new ProgramScope();
LinkedHashMap<String, Value> bindings = new LinkedHashMap<>();
{
Variable v1 = new Variable("z1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v2 = new Variable("z2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v3 = new Variable("z3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v4 = new Variable("z4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v5 = new Variable("z5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v6 = new Variable("z6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
Variable v1 = new Variable("z1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE);
Variable v2 = new Variable("z2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE);
Variable v3 = new Variable("z3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE);
Variable v4 = new Variable("z4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE);
Variable v5 = new Variable("z5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE);
Variable v6 = new Variable("z6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION, SymbolVariable.MemoryArea.ZEROPAGE);
v1.setAllocation(new Registers.RegisterZpMem(2, 1));
v2.setAllocation(new Registers.RegisterZpMem(4, 1));
v3.setAllocation(new Registers.RegisterZpMem(6, 1));
@ -100,12 +100,12 @@ public class AsmFragmentTemplate {
if(signature.contains("z6")) bindings.put("z6", v6);
}
{
Variable v1 = new Variable("m1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v2 = new Variable("m2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v3 = new Variable("m3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v4 = new Variable("m4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v5 = new Variable("m5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v6 = new Variable("m6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
Variable v1 = new Variable("m1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY);
Variable v2 = new Variable("m2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY);
Variable v3 = new Variable("m3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY);
Variable v4 = new Variable("m4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY);
Variable v5 = new Variable("m5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY);
Variable v6 = new Variable("m6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY, SymbolVariable.MemoryArea.MAIN_MEMORY);
v1.setAllocation(new Registers.RegisterMainMem(v1.getRef(), 1));
v2.setAllocation(new Registers.RegisterMainMem(v2.getRef(), 1));
v3.setAllocation(new Registers.RegisterMainMem(v3.getRef(), 1));

View File

@ -12,7 +12,7 @@ public class ConstantVar extends SymbolVariable {
private ConstantValue value;
public ConstantVar(String name, Scope scope, SymbolType type, ConstantValue value, String dataSegment) {
super(name, scope, type, StorageStrategy.CONSTANT, dataSegment);
super(name, scope, type, StorageStrategy.CONSTANT, MemoryArea.NONE, dataSegment);
this.value = value;
}

View File

@ -99,13 +99,13 @@ public abstract class Scope implements Symbol, Serializable {
symbols.remove(symbol.getLocalName());
}
public Variable addVariablePhiMaster(String name, SymbolType type, String dataSegment) {
return add(new Variable(name, this, type, dataSegment, SymbolVariable.StorageStrategy.PHI_MASTER));
public Variable addVariablePhiMaster(String name, SymbolType type, SymbolVariable.MemoryArea memoryArea, String dataSegment) {
return add(new Variable(name, this, type, dataSegment, SymbolVariable.StorageStrategy.PHI_MASTER, memoryArea));
}
public Variable addVariableIntermediate() {
String name = allocateIntermediateVariableName();
return add(new Variable(name, this, SymbolType.VAR, getSegmentData(), SymbolVariable.StorageStrategy.INTERMEDIATE));
return add(new Variable(name, this, SymbolType.VAR, getSegmentData(), SymbolVariable.StorageStrategy.INTERMEDIATE, SymbolVariable.MemoryArea.ZEROPAGE));
}
/**

View File

@ -55,16 +55,23 @@ public abstract class SymbolVariable implements Symbol {
/** 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_REGISTER-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>MEMORY-variables are stored in memory and accessed through load/store operators. They cannot be declared as "register".</li>
* <li>CONSTANT-variables are constant.
* <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>
* <li>MEMORY variables are stored in memory and accessed through load/store operations. They cannot be declared as "register".</li>
* <li>CONSTANT variables are constant.
* </ul>
**/
public enum StorageStrategy {PHI_MASTER, PHI_VERSION, INTERMEDIATE, MEMORY, CONSTANT }
public enum StorageStrategy { PHI_MASTER, PHI_VERSION, INTERMEDIATE, MEMORY, 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, MAIN_MEMORY }
/** The memory area where the variable lives (if stored in memory). */
private MemoryArea memoryArea;
/** Comments preceding the procedure in the source code. */
private List<Comment> comments;
@ -75,7 +82,7 @@ public abstract class SymbolVariable implements Symbol {
private String dataSegment;
public SymbolVariable(String name, Scope scope, SymbolType type, StorageStrategy storageStrategy, String dataSegment) {
public SymbolVariable(String name, Scope scope, SymbolType type, StorageStrategy storageStrategy, MemoryArea memoryArea, String dataSegment) {
this.name = name;
this.scope = scope;
this.type = type;
@ -83,6 +90,7 @@ public abstract class SymbolVariable implements Symbol {
this.comments = new ArrayList<>();
this.dataSegment = dataSegment;
this.storageStrategy = storageStrategy;
this.memoryArea = memoryArea;
setFullName();
}
@ -265,6 +273,22 @@ public abstract class SymbolVariable implements Symbol {
return StorageStrategy.INTERMEDIATE.equals(getStorageStrategy());
}
public MemoryArea getMemoryArea() {
return memoryArea;
}
public void setMemoryArea(MemoryArea memoryArea) {
this.memoryArea = memoryArea;
}
public boolean isMemoryAreaZp() {
return MemoryArea.ZEROPAGE.equals(getMemoryArea());
}
public boolean isMemoryAreaMain() {
return MemoryArea.MAIN_MEMORY.equals(getMemoryArea());
}
public List<Comment> getComments() {
return comments;
}

View File

@ -25,8 +25,8 @@ public class Variable extends SymbolVariable {
/** 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) {
super(name, scope, type, storageStrategy, dataSegment);
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;
}
@ -38,7 +38,7 @@ public class Variable extends SymbolVariable {
* @param version The version number
*/
public Variable(Variable phiMaster, int version) {
super(phiMaster.getName() + "#" + version, phiMaster.getScope(), phiMaster.getType(), StorageStrategy.PHI_VERSION, phiMaster.getDataSegment());
super(phiMaster.getName() + "#" + version, phiMaster.getScope(), phiMaster.getType(), StorageStrategy.PHI_VERSION, phiMaster.getMemoryArea(), phiMaster.getDataSegment());
this.setDeclaredAlignment(phiMaster.getDeclaredAlignment());
this.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister());
this.setDeclaredAsMemory(phiMaster.isDeclaredAsMemory());

View File

@ -43,6 +43,8 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
private StatementSequence sequence;
/** Used to build the scopes of the source file. */
private Stack<Scope> scopeStack;
/** The memory area used by default for variables. */
private SymbolVariable.MemoryArea defaultMemoryArea;
public Pass0GenerateStatementSequence(CParser cParser, KickCParser.FileContext fileCtx, Program program) {
this.cParser = cParser;
@ -50,6 +52,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
this.program = program;
this.sequence = program.getStatementSequence();
this.scopeStack = new Stack<>();
this.defaultMemoryArea = SymbolVariable.MemoryArea.ZEROPAGE;
scopeStack.push(program.getScope());
}
@ -201,7 +204,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Label procExit = procedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
Variable returnVar = null;
if(!SymbolType.VOID.equals(type)) {
returnVar = procedure.addVariablePhiMaster("return", type, procedure.getSegmentData());
returnVar = procedure.addVariablePhiMaster("return", type, defaultMemoryArea, procedure.getSegmentData());
}
List<Variable> parameterList = new ArrayList<>();
if(ctx.parameterListDecl() != null) {
@ -260,7 +263,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
this.visitDeclTypes(ctx.declTypes());
SymbolType type = declVarType;
List<Directive> directives = declVarDirectives;
Variable param = new Variable(ctx.NAME().getText(), getCurrentScope(), type, currentDataSegment, SymbolVariable.StorageStrategy.PHI_MASTER);
Variable param = new Variable(ctx.NAME().getText(), getCurrentScope(), type, currentDataSegment, SymbolVariable.StorageStrategy.PHI_MASTER, defaultMemoryArea);
// Add directives
addDirectives(param, type, directives, new StatementSource(ctx));
exitDeclTypes();
@ -613,7 +616,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Variable lValue;
try {
lValue = getCurrentScope().addVariablePhiMaster(varName, type, currentDataSegment);
lValue = getCurrentScope().addVariablePhiMaster(varName, type, defaultMemoryArea, currentDataSegment);
} catch(CompileError e) {
throw new CompileError(e.getMessage(), new StatementSource(ctx));
}
@ -623,6 +626,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
if(type instanceof SymbolTypeArray || type.equals(SymbolType.STRING)) {
lValue.setDeclaredConstant(true);
lValue.setStorageStrategy(SymbolVariable.StorageStrategy.CONSTANT);
lValue.setMemoryArea(SymbolVariable.MemoryArea.MAIN_MEMORY);
}
if(lValue.isDeclaredConstant()) {
// Add comments to constant
@ -681,6 +685,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
if(directive instanceof DirectiveConst) {
lValue.setDeclaredConstant(true);
lValue.setStorageStrategy(SymbolVariable.StorageStrategy.CONSTANT);
lValue.setMemoryArea(SymbolVariable.MemoryArea.MAIN_MEMORY);
} else if(directive instanceof DirectiveVolatile) {
lValue.setDeclaredVolatile(true);
} else if(directive instanceof DirectiveExport) {
@ -695,6 +700,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
DirectiveMemory directiveMemory = (DirectiveMemory) directive;
lValue.setDeclaredAsMemory(true);
lValue.setStorageStrategy(SymbolVariable.StorageStrategy.MEMORY);
lValue.setMemoryArea(SymbolVariable.MemoryArea.MAIN_MEMORY);
if(directiveMemory.address!=null) {
lValue.setDeclaredMemoryAddress(directiveMemory.address);
}
@ -1199,7 +1205,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Variable lValue;
if(varType != null) {
try {
lValue = getCurrentScope().addVariablePhiMaster(varName, varType, currentDataSegment);
lValue = getCurrentScope().addVariablePhiMaster(varName, varType, defaultMemoryArea, currentDataSegment);
} catch(CompileError e) {
throw new CompileError(e.getMessage(), statementSource);
}
@ -1625,7 +1631,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
scopeStack.push(typedefScope);
SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
String typedefName = ctx.NAME().getText();
typedefScope.addVariablePhiMaster(typedefName, type, currentDataSegment);
typedefScope.addVariablePhiMaster(typedefName, type, defaultMemoryArea, currentDataSegment);
scopeStack.pop();
return null;
}

View File

@ -300,7 +300,7 @@ public class Pass1ProcedureInline extends Pass1Base {
if(procSymbol instanceof Variable) {
Variable procVar = (Variable) procSymbol;
String inlineVarName = getInlineSymbolName(procedure, procSymbol, serial);
Variable inlineVar = callScope.addVariablePhiMaster(inlineVarName, procSymbol.getType(), procVar.getDataSegment());
Variable inlineVar = callScope.addVariablePhiMaster(inlineVarName, procSymbol.getType(), procVar.getMemoryArea(), procVar.getDataSegment());
inlineVar.setInferredType(procVar.isInferredType());
inlineVar.setDeclaredAlignment(procVar.getDeclaredAlignment());
inlineVar.setDeclaredConstant(procVar.isDeclaredConstant());
@ -309,6 +309,7 @@ public class Pass1ProcedureInline extends Pass1Base {
inlineVar.setDeclaredRegister(procVar.getDeclaredRegister());
inlineVar.setDeclaredMemoryAddress(procVar.getDeclaredMemoryAddress());
inlineVar.setStorageStrategy(procVar.getStorageStrategy());
inlineVar.setMemoryArea(procVar.getMemoryArea());
inlineVar.setDeclaredVolatile(procVar.isDeclaredVolatile());
inlineVar.setInferedVolatile(procVar.isInferedVolatile());
inlineVar.setDeclaredExport(procVar.isDeclaredExport());

View File

@ -76,7 +76,7 @@ public class Pass1UnwindBlockScopes extends Pass1Base {
if(variable.isStoragePhiMaster() || variable.isStorageConstant()) {
String name = findLocalName(procedure, symbol);
Variable var = (Variable) symbol;
Variable unwound = procedure.addVariablePhiMaster(name, symbol.getType(), var.getDataSegment());
Variable unwound = procedure.addVariablePhiMaster(name, symbol.getType(), var.getMemoryArea(), var.getDataSegment());
unwound.setDeclaredAlignment(var.getDeclaredAlignment());
unwound.setDeclaredConstant(var.isDeclaredConstant());
unwound.setDeclaredVolatile(var.isDeclaredVolatile());
@ -85,9 +85,11 @@ public class Pass1UnwindBlockScopes extends Pass1Base {
unwound.setDeclaredExport(var.isDeclaredExport());
unwoundSymbols.put(symbol.getRef(), unwound.getRef());
unwound.setStorageStrategy(var.getStorageStrategy());
unwound.setMemoryArea(var.getMemoryArea());
} else if(variable.isStorageIntermediate()) {
Variable unwound = procedure.addVariableIntermediate();
unwound.setStorageStrategy(variable.getStorageStrategy());
unwound.setMemoryArea(variable.getMemoryArea());
unwoundSymbols.put(symbol.getRef(), unwound.getRef());
} else {
throw new CompileError("ERROR! Unexpected symbol encountered in block scope " + symbol.toString(getProgram()));

View File

@ -212,16 +212,18 @@ public class Pass1UnwindStructValues extends Pass1Base {
for(Variable member : structDefinition.getAllVariables(false)) {
Variable memberVariable;
if(variable.getRef().isIntermediate()) {
memberVariable = scope.add(new Variable(variable.getLocalName() + "_" + member.getLocalName(), scope, member.getType(), variable.getDataSegment(), SymbolVariable.StorageStrategy.INTERMEDIATE));
memberVariable = scope.add(new Variable(variable.getLocalName() + "_" + member.getLocalName(), scope, member.getType(), variable.getDataSegment(), SymbolVariable.StorageStrategy.INTERMEDIATE, variable.getMemoryArea()));
} else {
memberVariable = scope.addVariablePhiMaster(variable.getLocalName() + "_" + member.getLocalName(), member.getType(), variable.getDataSegment());
memberVariable = scope.addVariablePhiMaster(variable.getLocalName() + "_" + member.getLocalName(), member.getType(), member.getMemoryArea(), variable.getDataSegment());
}
memberVariable.setDeclaredVolatile(variable.isDeclaredVolatile());
memberVariable.setInferedVolatile(variable.isInferedVolatile());
memberVariable.setDeclaredConstant(variable.isDeclaredConstant());
memberVariable.setDeclaredExport(variable.isDeclaredExport());
if(variable.isStorageMemory() && member.isStoragePhiMaster())
memberVariable.setStorageStrategy(SymbolVariable.StorageStrategy.MEMORY);
if(variable.isStorageMemory() && member.isStoragePhiMaster()) {
memberVariable.setStorageStrategy(variable.getStorageStrategy());
memberVariable.setMemoryArea(variable.getMemoryArea());
}
variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef());
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
}

View File

@ -465,7 +465,7 @@ public class Pass4CodeGeneration {
// Add all memory variables
Collection<Variable> scopeVariables = scope.getAllVariables(false);
for(Variable variable : scopeVariables) {
if(variable.isStorageMemory()) {
if(variable.isMemoryAreaMain()) {
// Skip if already added
String asmName = variable.getAsmName() == null ? variable.getLocalName() : variable.getAsmName();
if(added.contains(asmName)) {

View File

@ -181,7 +181,7 @@ public class Pass4RegistersFinalize extends Pass2Base {
String before = register == null ? null : register.toString();
VariableRef variableRef = equivalenceClass.getVariables().get(0);
Variable variable = getProgram().getSymbolInfos().getVariable(variableRef);
if(variable.isStorageMemory()) {
if(variable.isMemoryAreaMain()) {
register = new Registers.RegisterMainMem(variableRef, variable.getType().getSizeBytes());
} else {
register = allocateNewRegisterZp(variable);

View File

@ -137,9 +137,11 @@ public class PassNTypeInference extends Pass2SsaOptimization {
if(symbol.getType() instanceof SymbolTypeArray) {
symbol.setDeclaredConstant(true);
symbol.setStorageStrategy(SymbolVariable.StorageStrategy.CONSTANT);
symbol.setMemoryArea(SymbolVariable.MemoryArea.NONE);
} else if(SymbolType.STRING.equals(symbol.getType())) {
symbol.setDeclaredConstant(true);
symbol.setStorageStrategy(SymbolVariable.StorageStrategy.CONSTANT);
symbol.setMemoryArea(SymbolVariable.MemoryArea.NONE);
}
}
}

View File

@ -236,6 +236,7 @@ public class Unroller {
newVar.setDeclaredAsMemory(definedVar.isDeclaredAsMemory());
newVar.setDeclaredMemoryAddress(definedVar.getDeclaredMemoryAddress());
newVar.setStorageStrategy(definedVar.getStorageStrategy());
newVar.setMemoryArea(definedVar.getMemoryArea());
newVar.setDeclaredVolatile(definedVar.isDeclaredVolatile());
newVar.setInferedVolatile(definedVar.isInferedVolatile());
newVar.setDeclaredExport(definedVar.isDeclaredExport());