1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-11 04:29:53 +00:00

Restructured Variable creation to make it more explicit what type is being created.

This commit is contained in:
jespergravgaard 2019-12-08 17:49:14 +01:00
parent 2bad8c915f
commit cff815f5d7
16 changed files with 171 additions and 111 deletions

View File

@ -79,12 +79,13 @@ public class AsmFragmentTemplate {
ProgramScope scope = new ProgramScope(); ProgramScope scope = new ProgramScope();
LinkedHashMap<String, Value> bindings = new LinkedHashMap<>(); LinkedHashMap<String, Value> bindings = new LinkedHashMap<>();
{ {
Variable v1 = new Variable( "z1", Variable.Kind.PHI_VERSION, SymbolType.BYTE, scope, Variable.MemoryArea.ZEROPAGE_MEMORY, null); Variable master = Variable.createPhiMaster("z", SymbolType.BYTE, scope, Variable.MemoryArea.ZEROPAGE_MEMORY, null);
Variable v2 = new Variable( "z2", Variable.Kind.PHI_VERSION, SymbolType.BYTE, scope, Variable.MemoryArea.ZEROPAGE_MEMORY, null); Variable v1 = Variable.createPhiVersion(master, 1); v1.setName("z1");
Variable v3 = new Variable( "z3", Variable.Kind.PHI_VERSION, SymbolType.BYTE, scope, Variable.MemoryArea.ZEROPAGE_MEMORY, null); Variable v2 = Variable.createPhiVersion(master, 2); v2.setName("z2");
Variable v4 = new Variable( "z4", Variable.Kind.PHI_VERSION, SymbolType.BYTE, scope, Variable.MemoryArea.ZEROPAGE_MEMORY, null); Variable v3 = Variable.createPhiVersion(master, 3); v3.setName("z3");
Variable v5 = new Variable( "z5", Variable.Kind.PHI_VERSION, SymbolType.BYTE, scope, Variable.MemoryArea.ZEROPAGE_MEMORY, null); Variable v4 = Variable.createPhiVersion(master, 4); v4.setName("z4");
Variable v6 = new Variable( "z6", Variable.Kind.PHI_VERSION, SymbolType.BYTE, scope, Variable.MemoryArea.ZEROPAGE_MEMORY, null); Variable v5 = Variable.createPhiVersion(master, 5); v5.setName("z5");
Variable v6 = Variable.createPhiVersion(master, 6); v6.setName("z6");
v1.setAllocation(new Registers.RegisterZpMem(2, 1)); v1.setAllocation(new Registers.RegisterZpMem(2, 1));
v2.setAllocation(new Registers.RegisterZpMem(4, 1)); v2.setAllocation(new Registers.RegisterZpMem(4, 1));
v3.setAllocation(new Registers.RegisterZpMem(6, 1)); v3.setAllocation(new Registers.RegisterZpMem(6, 1));
@ -99,12 +100,12 @@ public class AsmFragmentTemplate {
if(signature.contains("z6")) bindings.put("z6", v6); if(signature.contains("z6")) bindings.put("z6", v6);
} }
{ {
Variable v1 = new Variable( "m1", Variable.Kind.LOAD_STORE, SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null); Variable v1 = Variable.createLoadStore("m1", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
Variable v2 = new Variable( "m2", Variable.Kind.LOAD_STORE, SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null); Variable v2 = Variable.createLoadStore("m2", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
Variable v3 = new Variable( "m3", Variable.Kind.LOAD_STORE, SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null); Variable v3 = Variable.createLoadStore("m3", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
Variable v4 = new Variable( "m4", Variable.Kind.LOAD_STORE, SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null); Variable v4 = Variable.createLoadStore("m4", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
Variable v5 = new Variable( "m5", Variable.Kind.LOAD_STORE, SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null); Variable v5 = Variable.createLoadStore("m5", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
Variable v6 = new Variable( "m6", Variable.Kind.LOAD_STORE, SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null); Variable v6 = Variable.createLoadStore("m6", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
v1.setAllocation(new Registers.RegisterMainMem(v1.getVariableRef(), 1, null)); v1.setAllocation(new Registers.RegisterMainMem(v1.getVariableRef(), 1, null));
v2.setAllocation(new Registers.RegisterMainMem(v2.getVariableRef(), 1, null)); v2.setAllocation(new Registers.RegisterMainMem(v2.getVariableRef(), 1, null));
v3.setAllocation(new Registers.RegisterMainMem(v3.getVariableRef(), 1, null)); v3.setAllocation(new Registers.RegisterMainMem(v3.getVariableRef(), 1, null));

View File

@ -23,7 +23,7 @@ public class CallingConventionStack {
if(returnOffsetConstant == null) { if(returnOffsetConstant == null) {
// Constant not found - create it // Constant not found - create it
long returnByteOffset = getReturnByteOffset(procedure); long returnByteOffset = getReturnByteOffset(procedure);
returnOffsetConstant = new Variable(returnOffsetConstantName, SymbolType.BYTE, null, procedure, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(returnByteOffset & 0xff, SymbolType.BYTE)); returnOffsetConstant = Variable.createConstant(returnOffsetConstantName, SymbolType.BYTE, procedure, null, new ConstantInteger(returnByteOffset & 0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
procedure.add(returnOffsetConstant); procedure.add(returnOffsetConstant);
} }
return returnOffsetConstant.getConstantRef(); return returnOffsetConstant.getConstantRef();
@ -42,7 +42,7 @@ public class CallingConventionStack {
if(paramOffsetConstant == null) { if(paramOffsetConstant == null) {
// Constant not found - create it // Constant not found - create it
long paramByteOffset = getParameterByteOffset(procedure, parameter); long paramByteOffset = getParameterByteOffset(procedure, parameter);
paramOffsetConstant = new Variable(paramOffsetConstantName, SymbolType.BYTE, null, procedure, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(paramByteOffset & 0xff, SymbolType.BYTE)); paramOffsetConstant = Variable.createConstant(paramOffsetConstantName, SymbolType.BYTE, procedure, null, new ConstantInteger(paramByteOffset & 0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
procedure.add(paramOffsetConstant); procedure.add(paramOffsetConstant);
} }
return paramOffsetConstant.getConstantRef(); return paramOffsetConstant.getConstantRef();
@ -123,7 +123,7 @@ public class CallingConventionStack {
*/ */
public static ConstantRef getStackBaseConstant(ProgramScope programScope) { public static ConstantRef getStackBaseConstant(ProgramScope programScope) {
long STACK_BASE_ADDRESS = 0x103L; long STACK_BASE_ADDRESS = 0x103L;
Variable stackBase = new Variable("STACK_BASE", SymbolType.WORD, null, programScope, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(STACK_BASE_ADDRESS, SymbolType.WORD)); Variable stackBase = Variable.createConstant("STACK_BASE", SymbolType.WORD, programScope, null, new ConstantInteger(STACK_BASE_ADDRESS, SymbolType.WORD), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(stackBase); programScope.add(stackBase);
return stackBase.getConstantRef(); return stackBase.getConstantRef();
} }

View File

@ -42,7 +42,7 @@ public class OperatorSizeOf extends OperatorUnary {
if(typeSizeConstant == null) { if(typeSizeConstant == null) {
// Constant not found - create it // Constant not found - create it
long typeSize = type.getSizeBytes(); long typeSize = type.getSizeBytes();
typeSizeConstant = new Variable(typeConstName, SymbolType.BYTE, null, programScope, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(typeSize&0xff, SymbolType.BYTE)); typeSizeConstant = Variable.createConstant(typeConstName, SymbolType.BYTE, programScope, null, new ConstantInteger(typeSize&0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(typeSizeConstant); programScope.add(typeSizeConstant);
} }
return typeSizeConstant.getConstantRef(); return typeSizeConstant.getConstantRef();

View File

@ -47,7 +47,7 @@ public class OperatorTypeId extends OperatorUnary {
if(typeIdConstant == null) { if(typeIdConstant == null) {
// Constant not found - create it // Constant not found - create it
long typeSize = getTypeId(type); long typeSize = getTypeId(type);
typeIdConstant = new Variable(typeConstName, SymbolType.BYTE, null, programScope, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(typeSize)); typeIdConstant = Variable.createConstant(typeConstName, SymbolType.BYTE, programScope, null, new ConstantInteger(typeSize), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(typeIdConstant); programScope.add(typeIdConstant);
} }
return typeIdConstant.getConstantRef(); return typeIdConstant.getConstantRef();

View File

@ -100,17 +100,9 @@ public abstract class Scope implements Symbol, Serializable {
symbols.remove(symbol.getLocalName()); symbols.remove(symbol.getLocalName());
} }
public Variable addVariable(Variable.Kind kind, String name, SymbolType type, Variable.MemoryArea memoryArea, String dataSegment) {
return add(new Variable( name, kind, type, this, memoryArea, dataSegment));
}
public Variable addVariablePhiMaster(String name, SymbolType type, Variable.MemoryArea memoryArea, String dataSegment) {
return add(new Variable( name, Variable.Kind.PHI_MASTER, type, this, memoryArea, dataSegment));
}
public Variable addVariableIntermediate() { public Variable addVariableIntermediate() {
String name = allocateIntermediateVariableName(); String name = allocateIntermediateVariableName();
return add(new Variable( name, Variable.Kind.INTERMEDIATE, SymbolType.VAR, this, Variable.MemoryArea.ZEROPAGE_MEMORY, getSegmentData())); return add(Variable.createIntermediate( name, this, getSegmentData()));
} }
/** /**

View File

@ -5,6 +5,7 @@ import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.Registers; import dk.camelot64.kickc.model.Registers;
import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.values.ConstantRef; import dk.camelot64.kickc.model.values.ConstantRef;
import dk.camelot64.kickc.model.values.ConstantValue; import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.SymbolVariableRef; import dk.camelot64.kickc.model.values.SymbolVariableRef;
@ -14,12 +15,12 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/** A Variable symbol (can either be a runtime variable or a compile-time constant)*/ /** A Variable symbol (can either be a runtime variable or a compile-time constant) */
public class Variable implements Symbol { public class Variable implements Symbol {
/** /**
* The kind of the variable. The kind is the most significant property of the variable since it drives most of the behavior. * The kind of the variable. The kind is the most significant property of the variable since it drives most of the behavior.
* * <p>
* The value depends on the directives memory/register/volatile/const - and on the compilers optimization decisions. * The value depends on the directives memory/register/volatile/const - and on the compilers optimization decisions.
* <ul> * <ul>
* <li>PHI_MASTER variables are turned into PHI-versions and PHI-nodes are used for them throughout the entire program. The PHI-master itself is only an information container and does not live in memory at runtime.</li> * <li>PHI_MASTER variables are turned into PHI-versions and PHI-nodes are used for them throughout the entire program. The PHI-master itself is only an information container and does not live in memory at runtime.</li>
@ -33,7 +34,7 @@ public class Variable implements Symbol {
PHI_MASTER, PHI_VERSION, INTERMEDIATE, LOAD_STORE, CONSTANT PHI_MASTER, PHI_VERSION, INTERMEDIATE, LOAD_STORE, CONSTANT
} }
/** The kind of the variable. */ /** The kind of the variable. */
private Kind kind; private Kind kind;
/** The local name of the variable. [ALL] */ /** The local name of the variable. [ALL] */
@ -42,13 +43,13 @@ public class Variable implements Symbol {
/** Full name of variable including scope (scope::name or name) [ALL] */ /** Full name of variable including scope (scope::name or name) [ALL] */
private String fullName; private String fullName;
/** 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. [ALL]*/ /** 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. [ALL] */
private String asmName; private String asmName;
/** The scope containing the variable. [ALL] */ /** The scope containing the variable. [ALL] */
private Scope scope; private Scope scope;
/** The type of the variable. VAR means the type is unknown, and has not been inferred yet. [ALL]*/ /** The type of the variable. VAR means the type is unknown, and has not been inferred yet. [ALL] */
private SymbolType type; private SymbolType type;
/** Specifies that the variable must be aligned in memory. Only allowed for arrays & strings. [Only Variables in memory and arrays] */ /** Specifies that the variable must be aligned in memory. Only allowed for arrays & strings. [Only Variables in memory and arrays] */
@ -60,7 +61,7 @@ public class Variable implements Symbol {
/** Specifies that the variable is declared as const */ /** Specifies that the variable is declared as const */
private boolean declaredConst; private boolean declaredConst;
/** Specifies that the variable must always live in memory to be available for any multi-threaded accees (eg. in interrupts). [Only Variables]*/ /** Specifies that the variable must always live in memory to be available for any multi-threaded accees (eg. in interrupts). [Only Variables] */
private boolean declaredVolatile; private boolean declaredVolatile;
/** Specifies that the variable must always live in memory to be available for any multi-threaded accees (eg. in interrupts). [Only variables] TODO: Remove this */ /** Specifies that the variable must always live in memory to be available for any multi-threaded accees (eg. in interrupts). [Only variables] TODO: Remove this */
@ -84,7 +85,7 @@ public class Variable implements Symbol {
/** The constant value if the variable is a constant. Null otherwise. [Only constants] */ /** The constant value if the variable is a constant. Null otherwise. [Only constants] */
private ConstantValue constantValue; private ConstantValue constantValue;
/** Non-null if the variable is an array. [Only constants that are arrays]*/ /** Non-null if the variable is an array. [Only constants that are arrays] */
private ArraySpec arraySpec; private ArraySpec arraySpec;
/** The number of the next version (only used for PHI masters) [Only PHI masters] */ /** The number of the next version (only used for PHI masters) [Only PHI masters] */
@ -99,21 +100,26 @@ public class Variable implements Symbol {
} }
/** /**
* Create a runtime variable * Create a variable (or constant)
*
* @param name The name * @param name The name
* @param kind The storage strategy (PHI-master/PHI-version/Intermediate/load store/constant) * @param kind The storage strategy (PHI-master/PHI-version/Intermediate/load store/constant)
* @param type The type * @param type The type
* @param scope The scope * @param scope The scope
* @param memoryArea The memory area (zeropage/main memory) * @param memoryArea The memory area (zeropage/main memory)
* @param dataSegment The data segment (in main memory) * @param dataSegment The data segment (in main memory)
* @param arraySpec The array specification of the variable (if it is an array)
* @param constantValue The constant value of the variable (if it is constant)
*/ */
public Variable(String name, Kind kind, SymbolType type, Scope scope, MemoryArea memoryArea, String dataSegment) { private Variable(String name, Kind kind, SymbolType type, Scope scope, MemoryArea memoryArea, String dataSegment, ArraySpec arraySpec, ConstantValue constantValue) {
this.name = name; this.name = name;
this.kind = kind; this.kind = kind;
if(Kind.PHI_MASTER.equals(kind)) if(Kind.PHI_MASTER.equals(kind))
this.nextPhiVersionNumber = 0; this.nextPhiVersionNumber = 0;
this.type = type; this.type = type;
this.scope = scope; this.scope = scope;
this.arraySpec = arraySpec;
this.constantValue = constantValue;
this.dataSegment = dataSegment; this.dataSegment = dataSegment;
this.memoryArea = memoryArea; this.memoryArea = memoryArea;
this.comments = new ArrayList<>(); this.comments = new ArrayList<>();
@ -121,74 +127,132 @@ public class Variable implements Symbol {
} }
/** /**
* Create a compile-time constant variable * Create an intermediate variable. The type will initially be set to {@link SymbolType#VAR}.
*
* @param name The name * @param name The name
* @param type The type
* @param scope The scope * @param scope The scope
* @param dataSegment The data segment (in main memory) * @param dataSegment The data segment (in main memory)
* @param value The constant value * @return The new intermediate variable
*/ */
public Variable(String name, SymbolType type, ArraySpec arraySpec, Scope scope, String dataSegment, ConstantValue value) { public static Variable createIntermediate(String name, Scope scope, String dataSegment) {
this(name, Kind.CONSTANT, type, scope, MemoryArea.MAIN_MEMORY, dataSegment); return new Variable(name, Kind.INTERMEDIATE, SymbolType.VAR, scope, MemoryArea.ZEROPAGE_MEMORY, dataSegment, null, null);
this.arraySpec = arraySpec;
this.constantValue = value;
} }
/** /**
* Create a constant version of a variable * Create a load/store variable
* @param variable The variable to create a constant version of *
* @param constVal The constant value * @param name The name
* @param type The type
* @param scope The scope
* @param memoryArea The memory area (zeropage/main memory)
* @param dataSegment The data segment (in main memory)
* @return The new PHI-master variable
*/ */
public Variable(Variable variable, ConstantValue constVal) { public static Variable createLoadStore(String name, SymbolType type, Scope scope, Variable.MemoryArea memoryArea, String dataSegment) {
this(variable.getName(),variable.getType(), variable.getArraySpec(), variable.getScope(), variable.getDataSegment(), constVal); return new Variable(name, Kind.LOAD_STORE, type, scope, memoryArea, dataSegment, null, null);
this.setDeclaredAlignment(variable.getDeclaredAlignment()); }
this.setDeclaredAsRegister(variable.isDeclaredAsRegister());
this.setDeclaredConst(variable.isDeclaredConst()); /**
this.setDeclaredRegister(variable.getDeclaredRegister()); * Create a PHI master variable
this.setDeclaredVolatile(variable.isDeclaredVolatile()); *
this.setDeclaredExport(variable.isDeclaredExport()); * @param name The name
this.setInferredVolatile(variable.isInferredVolatile()); * @param type The type
this.setComments(variable.getComments()); * @param scope The scope
* @param memoryArea The memory area (zeropage/main memory)
* @param dataSegment The data segment (in main memory)
* @return The new PHI-master variable
*/
public static Variable createPhiMaster(String name, SymbolType type, Scope scope, Variable.MemoryArea memoryArea, String dataSegment) {
return new Variable(name, Kind.PHI_MASTER, type, scope, memoryArea, dataSegment, null, null);
} }
/** /**
* Create a version of a PHI master variable * Create a version of a PHI master variable
* *
* @param phiMaster The PHI master variable. * @param phiMaster The PHI master variable.
* @param version The version number * @param versionNum The version number
*/ */
private Variable(Variable phiMaster, int version) { public static Variable createPhiVersion(Variable phiMaster, int versionNum) {
this(phiMaster.getName() + "#" + version, Kind.PHI_VERSION, phiMaster.getType(), phiMaster.getScope(), phiMaster.getMemoryArea(), phiMaster.getDataSegment()); Variable version = new Variable(phiMaster.getName() + "#" + versionNum, Kind.PHI_VERSION, phiMaster.getType(), phiMaster.getScope(), phiMaster.getMemoryArea(), phiMaster.getDataSegment(), phiMaster.getArraySpec(), null);
this.setArraySpec(phiMaster.getArraySpec()); version.setDeclaredAlignment(phiMaster.getDeclaredAlignment());
this.setDeclaredAlignment(phiMaster.getDeclaredAlignment()); version.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister());
this.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister()); version.setDeclaredConst(phiMaster.isDeclaredConst());
this.setDeclaredConst(phiMaster.isDeclaredConst()); version.setDeclaredRegister(phiMaster.getDeclaredRegister());
this.setDeclaredRegister(phiMaster.getDeclaredRegister()); version.setDeclaredVolatile(phiMaster.isDeclaredVolatile());
this.setDeclaredVolatile(phiMaster.isDeclaredVolatile()); version.setDeclaredExport(phiMaster.isDeclaredExport());
this.setDeclaredExport(phiMaster.isDeclaredExport()); version.setInferredVolatile(phiMaster.isInferredVolatile());
this.setInferredVolatile(phiMaster.isInferredVolatile()); version.setComments(phiMaster.getComments());
this.setComments(phiMaster.getComments()); return version;
}
/**
* Create a compile-time constant variable
*
* @param name The name
* @param type The type
* @param scope The scope
* @param value The constant value
* @param dataSegment The data segment (in main memory)
*/
public static Variable createConstant(String name, SymbolType type, Scope scope, ArraySpec arraySpec, ConstantValue value, String dataSegment) {
return new Variable(name, Kind.CONSTANT, type, scope, MemoryArea.MAIN_MEMORY, dataSegment, arraySpec, value);
}
/**
* Create a constant version of a variable. Used when a variable is determined to be constant during the compile.
*
* @param variable The variable to create a constant version of
* @param constVal The constant value
*/
public static Variable createConstant(Variable variable, ConstantValue constVal) {
Variable constVar = createConstant(variable.getName(), variable.getType(), variable.getScope(), variable.getArraySpec(), constVal, variable.getDataSegment());
constVar.setDeclaredAlignment(variable.getDeclaredAlignment());
constVar.setDeclaredAsRegister(variable.isDeclaredAsRegister());
constVar.setDeclaredConst(variable.isDeclaredConst());
constVar.setDeclaredRegister(variable.getDeclaredRegister());
constVar.setDeclaredVolatile(variable.isDeclaredVolatile());
constVar.setDeclaredExport(variable.isDeclaredExport());
constVar.setInferredVolatile(variable.isInferredVolatile());
constVar.setComments(variable.getComments());
return constVar;
} }
/** /**
* Create a copy of a variable with a different name in a different scope * Create a copy of a variable with a different name in a different scope
* *
* @param name The name * @param name The name for the new variable
* @param scope The scope * @param scope The scope for the new variable
* @param original The original variable * @param original The original variable
*/ */
public Variable(String name, Scope scope, Variable original) { public static Variable createCopy(String name, Scope scope, Variable original) {
this(name, original.getKind(), original.getType(), scope, original.getMemoryArea(), original.getDataSegment()); Variable copy = new Variable(name, original.getKind(), original.getType(), scope, original.getMemoryArea(), original.getDataSegment(), original.getArraySpec(), original.getConstantValue());
this.setArraySpec(original.getArraySpec()); copy.setDeclaredAlignment(original.getDeclaredAlignment());
this.setDeclaredAlignment(original.getDeclaredAlignment()); copy.setDeclaredAsRegister(original.isDeclaredAsRegister());
this.setDeclaredAsRegister(original.isDeclaredAsRegister()); copy.setDeclaredConst(original.isDeclaredConst());
this.setDeclaredConst(original.isDeclaredConst()); copy.setDeclaredVolatile(original.isDeclaredVolatile());
this.setDeclaredVolatile(original.isDeclaredVolatile()); copy.setDeclaredExport(original.isDeclaredExport());
this.setDeclaredExport(original.isDeclaredExport()); copy.setDeclaredRegister(original.getDeclaredRegister());
this.setDeclaredRegister(original.getDeclaredRegister()); copy.setInferredVolatile(original.isInferredVolatile());
this.setInferredVolatile(original.isInferredVolatile()); copy.setComments(original.getComments());
this.setComments(original.getComments()); return copy;
this.setConstantValue(original.getConstantValue()); }
/**
* Create a variable representing a single member of a struct variable.
* @param structVar The variable that holds a struct value.
* @param memberDefinition The definition of the struct member
* @return The new unwound variable representing the member of the struct
*/
public static Variable createStructMemberUnwound(Variable structVar, Variable memberDefinition) {
String name = structVar.getLocalName() + "_" + memberDefinition.getLocalName();
Variable.MemoryArea memoryArea = (memberDefinition.getType() instanceof SymbolTypePointer) ? Variable.MemoryArea.ZEROPAGE_MEMORY : structVar.getMemoryArea();
Variable memberVariable = new Variable(name, structVar.getKind(), memberDefinition.getType(), structVar.getScope(), memoryArea, structVar.getDataSegment(), null, null);
memberVariable.setArraySpec(memberDefinition.getArraySpec());
memberVariable.setDeclaredVolatile(structVar.isDeclaredVolatile());
memberVariable.setInferredVolatile(structVar.isInferredVolatile());
memberVariable.setDeclaredConst(structVar.isDeclaredConst());
memberVariable.setDeclaredExport(structVar.isDeclaredExport());
return memberVariable;
} }
public Kind getKind() { public Kind getKind() {
@ -252,7 +316,7 @@ public class Variable implements Symbol {
public Variable createVersion() { public Variable createVersion() {
if(!isKindPhiMaster()) if(!isKindPhiMaster())
throw new InternalError("Cannot version non-PHI variable " + this.toString()); throw new InternalError("Cannot version non-PHI variable " + this.toString());
Variable version = new Variable(this, nextPhiVersionNumber++); Variable version = Variable.createPhiVersion(this, nextPhiVersionNumber++);
getScope().add(version); getScope().add(version);
return version; return version;
} }
@ -271,7 +335,7 @@ public class Variable implements Symbol {
} }
public boolean isArray() { public boolean isArray() {
return arraySpec!=null; return arraySpec != null;
} }
public ArraySpec getArraySpec() { public ArraySpec getArraySpec() {

View File

@ -4,6 +4,7 @@ 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.model.*; import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.iterator.ProgramValue; import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.operators.*; import dk.camelot64.kickc.model.operators.*;
import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.statements.*;
@ -208,7 +209,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Label procExit = procedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME); Label procExit = procedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
Variable returnVar = null; Variable returnVar = null;
if(!SymbolType.VOID.equals(type)) { if(!SymbolType.VOID.equals(type)) {
returnVar = procedure.addVariablePhiMaster("return", type, defaultMemoryArea, procedure.getSegmentData()); returnVar = procedure.add(Variable.createPhiMaster("return", type, procedure, defaultMemoryArea, procedure.getSegmentData()));
} }
List<Variable> parameterList = new ArrayList<>(); List<Variable> parameterList = new ArrayList<>();
if(ctx.parameterListDecl() != null) { if(ctx.parameterListDecl() != null) {
@ -267,7 +268,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
this.visitDeclTypes(ctx.declTypes()); this.visitDeclTypes(ctx.declTypes());
SymbolType type = declVarType; SymbolType type = declVarType;
List<Directive> directives = declVarDirectives; List<Directive> directives = declVarDirectives;
Variable param = new Variable( ctx.NAME().getText(), Variable.Kind.PHI_MASTER, type, getCurrentScope(), defaultMemoryArea, currentDataSegment); Variable param = Variable.createPhiMaster( ctx.NAME().getText(), type, getCurrentScope(), defaultMemoryArea, currentDataSegment);
// Add directives // Add directives
directiveContext.applyDirectives(param, true, false, directives, new StatementSource(ctx)); directiveContext.applyDirectives(param, true, false, directives, new StatementSource(ctx));
exitDeclTypes(); exitDeclTypes();
@ -577,14 +578,22 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
arraySpec = new ArraySpec(declArraySize); arraySpec = new ArraySpec(declArraySize);
} }
Scope scope = getCurrentScope(); Scope scope = getCurrentScope();
Variable constVar = new Variable(varName, declVarType, arraySpec, scope, currentDataSegment, initConstantValue); Variable constVar = Variable.createConstant(varName, declVarType, scope, arraySpec, initConstantValue, currentDataSegment);
scope.add(constVar); scope.add(constVar);
// Add comments to constant // Add comments to constant
constVar.setComments(ensureUnusedComments(declVarComments)); constVar.setComments(ensureUnusedComments(declVarComments));
directiveContext.applyDirectives(constVar, false, declIsArray, declVarDirectives, statementSource); directiveContext.applyDirectives(constVar, false, declIsArray, declVarDirectives, statementSource);
} else { } else {
// Create variable // Create variable
Variable lValue = getCurrentScope().addVariable(kind, varName, declVarType, defaultMemoryArea, currentDataSegment); Variable lValue;
if(kind.equals(Variable.Kind.PHI_MASTER)) {
lValue = Variable.createPhiMaster(varName, declVarType, getCurrentScope(), defaultMemoryArea, currentDataSegment);
} else if (kind.equals(Variable.Kind.LOAD_STORE)) {
lValue = Variable.createLoadStore(varName, declVarType, getCurrentScope(), defaultMemoryArea, currentDataSegment);
} else {
throw new InternalError("Unexpected variable kind! "+kind.name(), statementSource);
}
getCurrentScope().add(lValue);
// Add directives // Add directives
directiveContext.applyDirectives(lValue, false, declIsArray, declVarDirectives, statementSource); directiveContext.applyDirectives(lValue, false, declIsArray, declVarDirectives, statementSource);
if(declVarStructMember) { if(declVarStructMember) {
@ -715,7 +724,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
} }
// Add a constant variable // Add a constant variable
Scope scope = getCurrentScope(); Scope scope = getCurrentScope();
Variable constVar = new Variable(varName, declVarType, arraySpec, scope, currentDataSegment, constantArrayKickAsm); Variable constVar = Variable.createConstant(varName, declVarType, scope, arraySpec, constantArrayKickAsm, currentDataSegment);
scope.add(constVar); scope.add(constVar);
// Add comments to constant // Add comments to constant
constVar.setComments(ensureUnusedComments(declVarComments)); constVar.setComments(ensureUnusedComments(declVarComments));
@ -1236,7 +1245,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Variable lValue; Variable lValue;
if(varType != null) { if(varType != null) {
try { try {
lValue = getCurrentScope().addVariablePhiMaster(varName, varType, defaultMemoryArea, currentDataSegment); lValue = getCurrentScope().add(Variable.createPhiMaster(varName, varType, getCurrentScope(), defaultMemoryArea, currentDataSegment));
} catch(CompileError e) { } catch(CompileError e) {
throw new CompileError(e.getMessage(), statementSource); throw new CompileError(e.getMessage(), statementSource);
} }
@ -1542,7 +1551,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Scope parentScope = getCurrentScope(); Scope parentScope = getCurrentScope();
while(parentScope instanceof StructDefinition) parentScope = parentScope.getScope(); while(parentScope instanceof StructDefinition) parentScope = parentScope.getScope();
for(Variable member : enumDefinition.getAllConstants(false)) { for(Variable member : enumDefinition.getAllConstants(false)) {
parentScope.add(new Variable(member.getLocalName(), SymbolType.BYTE, null, parentScope, currentDataSegment, member.getConstantValue())); parentScope.add(Variable.createConstant(member.getLocalName(), SymbolType.BYTE, parentScope, null, member.getConstantValue(), currentDataSegment));
} }
return SymbolType.BYTE; return SymbolType.BYTE;
} catch(CompileError e) { } catch(CompileError e) {
@ -1576,7 +1585,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
} }
} }
} }
currentEnum.add(new Variable(memberName, SymbolType.BYTE, null, getCurrentScope(), currentDataSegment, enumValue)); currentEnum.add(Variable.createConstant(memberName, SymbolType.BYTE, getCurrentScope(), null, enumValue, currentDataSegment));
return null; return null;
} }
@ -1661,7 +1670,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
scopeStack.push(typedefScope); scopeStack.push(typedefScope);
SymbolType type = (SymbolType) this.visit(ctx.typeDecl()); SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
String typedefName = ctx.NAME().getText(); String typedefName = ctx.NAME().getText();
typedefScope.addVariablePhiMaster(typedefName, type, defaultMemoryArea, currentDataSegment); typedefScope.add(Variable.createPhiMaster(typedefName, type, typedefScope, defaultMemoryArea, currentDataSegment));
scopeStack.pop(); scopeStack.pop();
return null; return null;
} }

View File

@ -120,7 +120,7 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
SymbolVariableRef variableRef = variable.getRef(); SymbolVariableRef variableRef = variable.getRef();
Scope scope = variable.getScope(); Scope scope = variable.getScope();
scope.remove(variable); scope.remove(variable);
Variable constVar = new Variable(variable, constantValue); Variable constVar = Variable.createConstant(variable, constantValue);
constVar.getComments().addAll(assignment.getComments()); constVar.getComments().addAll(assignment.getComments());
SymbolVariableRef constRef = constVar.getRef(); SymbolVariableRef constRef = constVar.getRef();
aliases.put(variableRef, constRef); aliases.put(variableRef, constRef);

View File

@ -74,7 +74,7 @@ public class Pass1ExtractInlineStrings extends Pass1Base {
name = nameHint + nameHintIdx++; name = nameHint + nameHintIdx++;
} }
} }
Variable strConst = new Variable(name, SymbolType.STRING, new ArraySpec(), blockScope, blockScope.getSegmentData(), constantString); Variable strConst = Variable.createConstant(name, SymbolType.STRING, blockScope, new ArraySpec(), constantString, blockScope.getSegmentData());
blockScope.add(strConst); blockScope.add(strConst);
if(getLog().isVerbosePass1CreateSsa()) { if(getLog().isVerbosePass1CreateSsa()) {
getLog().append("Creating constant string variable for inline " + strConst.toString(getProgram()) + " \"" + constantString.getValue() + "\""); getLog().append("Creating constant string variable for inline " + strConst.toString(getProgram()) + " \"" + constantString.getValue() + "\"");

View File

@ -300,7 +300,7 @@ public class Pass1ProcedureInline extends Pass1Base {
if(procSymbol instanceof Variable) { if(procSymbol instanceof Variable) {
Variable procVar = (Variable) procSymbol; Variable procVar = (Variable) procSymbol;
String inlineVarName = getInlineSymbolName(procedure, procSymbol, serial); String inlineVarName = getInlineSymbolName(procedure, procSymbol, serial);
Variable inlineVar = new Variable(inlineVarName, callScope, procVar); Variable inlineVar = Variable.createCopy(inlineVarName, callScope, procVar);
callScope.add(inlineVar); callScope.add(inlineVar);
} else if(procSymbol instanceof Label) { } else if(procSymbol instanceof Label) {
String inlineLabelName = getInlineSymbolName(procedure, procSymbol, serial); String inlineLabelName = getInlineSymbolName(procedure, procSymbol, serial);

View File

@ -72,17 +72,17 @@ public class Pass1UnwindBlockScopes extends Pass1Base {
Variable variable = (Variable) symbol; Variable variable = (Variable) symbol;
if(variable.isKindConstant()) { if(variable.isKindConstant()) {
String name = findLocalName(procedure, symbol); String name = findLocalName(procedure, symbol);
Variable unwound = new Variable(name, procedure, (Variable) symbol); Variable unwound = Variable.createCopy(name, procedure, (Variable) symbol);
procedure.add(unwound); procedure.add(unwound);
unwoundSymbols.put(symbol.getRef(), unwound.getRef()); unwoundSymbols.put(symbol.getRef(), unwound.getRef());
} else if(variable.isKindPhiMaster() || variable.isKindConstant()) { } else if(variable.isKindPhiMaster() || variable.isKindConstant()) {
String name = findLocalName(procedure, symbol); String name = findLocalName(procedure, symbol);
Variable unwound = new Variable(name, procedure, (Variable) symbol); Variable unwound = Variable.createCopy(name, procedure, (Variable) symbol);
procedure.add(unwound); procedure.add(unwound);
unwoundSymbols.put(symbol.getRef(), unwound.getRef()); unwoundSymbols.put(symbol.getRef(), unwound.getRef());
} else if(variable.isKindIntermediate()) { } else if(variable.isKindIntermediate()) {
String name = procedure.allocateIntermediateVariableName(); String name = procedure.allocateIntermediateVariableName();
Variable unwound = new Variable(name, procedure, (Variable) symbol); Variable unwound = Variable.createCopy(name, procedure, (Variable) symbol);
procedure.add(unwound); procedure.add(unwound);
unwoundSymbols.put(symbol.getRef(), unwound.getRef()); unwoundSymbols.put(symbol.getRef(), unwound.getRef());
} else { } else {

View File

@ -207,14 +207,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope()); StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef()); StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef());
for(Variable member : structDefinition.getAllVars(false)) { for(Variable member : structDefinition.getAllVars(false)) {
String name = variable.getLocalName() + "_" + member.getLocalName(); Variable memberVariable = Variable.createStructMemberUnwound(variable, member);
Variable.MemoryArea memoryArea = (member.getType() instanceof SymbolTypePointer)?Variable.MemoryArea.ZEROPAGE_MEMORY:variable.getMemoryArea(); scope.add(memberVariable);
Variable memberVariable = scope.add(new Variable( name, variable.getKind(), member.getType(), scope, memoryArea, variable.getDataSegment()));
memberVariable.setArraySpec(member.getArraySpec());
memberVariable.setDeclaredVolatile(variable.isDeclaredVolatile());
memberVariable.setInferredVolatile(variable.isInferredVolatile());
memberVariable.setDeclaredConst(variable.isDeclaredConst());
memberVariable.setDeclaredExport(variable.isDeclaredExport());
variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef()); variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef());
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram())); getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
} }

View File

@ -71,7 +71,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
); );
} }
scope.remove(variable); scope.remove(variable);
Variable constVar = new Variable(variable, constVal); Variable constVar = Variable.createConstant(variable, constVal);
constVar.getComments().addAll(constVarVal.getAssignment().getComments()); constVar.getComments().addAll(constVarVal.getAssignment().getComments());
scope.add(constVar); scope.add(constVar);
constAliases.put(constRef, constVar.getRef()); constAliases.put(constRef, constVar.getRef());

View File

@ -93,7 +93,7 @@ public class Pass2ConstantStringConsolidation extends Pass2SsaOptimization {
// Create a new root - and roll around again // Create a new root - and roll around again
ProgramScope rootScope = getScope(); ProgramScope rootScope = getScope();
String localName = getRootName(constantVars); String localName = getRootName(constantVars);
Variable newRootConstant = new Variable(localName, SymbolType.STRING, new ArraySpec(), rootScope, segmentData, constString); Variable newRootConstant = Variable.createConstant(localName, SymbolType.STRING, rootScope, new ArraySpec(), constString, segmentData);
rootScope.add(newRootConstant); rootScope.add(newRootConstant);
rootConstant = newRootConstant; rootConstant = newRootConstant;
} }

View File

@ -133,7 +133,7 @@ public class PassNStructPointerRewriting extends Pass2SsaOptimization {
// Constant not found - create it // Constant not found - create it
Variable memberDef = structDefinition.getMember(memberName); Variable memberDef = structDefinition.getMember(memberName);
long memberByteOffset = structDefinition.getMemberByteOffset(memberDef, programScope); long memberByteOffset = structDefinition.getMemberByteOffset(memberDef, programScope);
memberOffsetConstant = new Variable(typeConstName, SymbolType.BYTE, null, programScope, Scope.SEGMENT_DATA_DEFAULT, new ConstantInteger(memberByteOffset & 0xff, SymbolType.BYTE)); memberOffsetConstant = Variable.createConstant(typeConstName, SymbolType.BYTE, programScope, null, new ConstantInteger(memberByteOffset & 0xff, SymbolType.BYTE), Scope.SEGMENT_DATA_DEFAULT);
programScope.add(memberOffsetConstant); programScope.add(memberOffsetConstant);
} }
return memberOffsetConstant.getConstantRef(); return memberOffsetConstant.getConstantRef();

View File

@ -231,7 +231,7 @@ public class Unroller {
if(definedVarRef.isIntermediate()) { if(definedVarRef.isIntermediate()) {
Scope scope = definedVar.getScope(); Scope scope = definedVar.getScope();
String name = scope.allocateIntermediateVariableName(); String name = scope.allocateIntermediateVariableName();
newVar = new Variable(name, scope, definedVar); newVar = Variable.createCopy(name, scope, definedVar);
scope.add(newVar); scope.add(newVar);
} else if(definedVarRef.isVersion()) { } else if(definedVarRef.isVersion()) {
newVar = (definedVar).getVersionOf().createVersion(); newVar = (definedVar).getVersionOf().createVersion();