mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-08 14:37:40 +00:00
Changed declared const handling.
This commit is contained in:
parent
d9582d6b0f
commit
5839a98c60
@ -113,11 +113,11 @@ public class DirectiveParserContext {
|
||||
public void applyDirectives(Variable lValue, boolean isParameter, List<Directive> sourceDirectives, StatementSource source) {
|
||||
DirectiveType directiveType = DirectiveType.getFor(lValue.getType());
|
||||
if(hasDirective(Directive.Const.class, sourceDirectives))
|
||||
lValue.setConstantDeclaration(Variable.ConstantDeclaration.CONST);
|
||||
lValue.setDeclaredConst(true);
|
||||
if(directiveType.equals(DirectiveType.ARRAY))
|
||||
lValue.setConstantDeclaration(Variable.ConstantDeclaration.CONST);
|
||||
lValue.setDeclaredConst(true);
|
||||
if(hasDirective(Directive.NotConst.class, sourceDirectives))
|
||||
lValue.setConstantDeclaration(Variable.ConstantDeclaration.NOT_CONST);
|
||||
lValue.setDeclaredNotConst(true);
|
||||
if(hasDirective(Directive.Volatile.class, sourceDirectives))
|
||||
lValue.setDeclaredVolatile(true);
|
||||
if(hasDirective(Directive.Export.class, sourceDirectives))
|
||||
|
@ -30,7 +30,7 @@ public class OperatorDivide extends OperatorBinary {
|
||||
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||
if(left instanceof SymbolTypePointer) {
|
||||
if(SymbolType.isInteger(right)) {
|
||||
return left;
|
||||
return new SymbolTypePointer(((SymbolTypePointer) left).getElementType());
|
||||
} else {
|
||||
throw new NoMatchingType("Cannot divide pointer by "+right.toString());
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class OperatorMultiply extends OperatorBinary {
|
||||
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||
if(left instanceof SymbolTypePointer) {
|
||||
if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) {
|
||||
return left;
|
||||
return new SymbolTypePointer(((SymbolTypePointer) left).getElementType());
|
||||
} else {
|
||||
throw new NoMatchingType("Cannot multiply pointer by "+right.toString());
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class OperatorSetHigh extends OperatorBinary {
|
||||
@Override
|
||||
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||
if(left instanceof SymbolTypePointer) {
|
||||
return left;
|
||||
return new SymbolTypePointer(((SymbolTypePointer) left).getElementType());
|
||||
} else if(SymbolType.BYTE.equals(left)) {
|
||||
return SymbolType.WORD;
|
||||
} else if(SymbolType.SBYTE.equals(left)) {
|
||||
|
@ -20,7 +20,7 @@ public class OperatorSetLow extends OperatorBinary {
|
||||
@Override
|
||||
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||
if(left instanceof SymbolTypePointer) {
|
||||
return left;
|
||||
return new SymbolTypePointer(((SymbolTypePointer) left).getElementType());
|
||||
}
|
||||
if(SymbolType.WORD.equals(left)) {
|
||||
return SymbolType.WORD;
|
||||
|
@ -35,6 +35,15 @@ public class Variable implements Symbol {
|
||||
/** The storage strategy for the variable. */
|
||||
private Kind kind;
|
||||
|
||||
/** True of the variable is a compile-time constant (previously ConstantVar) [ALL] */
|
||||
private boolean isConstant;
|
||||
|
||||
/** Specifies that the variable is declared as const */
|
||||
private boolean declaredConst;
|
||||
|
||||
/** Specifies that the variable is declared as __notconst */
|
||||
private boolean declaredNotConst;
|
||||
|
||||
/** The local name of the variable. [ALL] */
|
||||
private String name;
|
||||
|
||||
@ -53,12 +62,6 @@ public class Variable implements Symbol {
|
||||
/** true if the symbol type is inferred (not declared) [kind:INTERMEDIATE] TODO: Collapse with kind==INTERMEDIATE? */
|
||||
private boolean inferredType;
|
||||
|
||||
/** True of the variable is a compile-time constant (previously ConstantVar) [ALL] */
|
||||
private boolean isConstant;
|
||||
|
||||
/** Specifies that the variable is declared a constant. It will be replaced by a ConstantVar when possible. [ALL] TODO: Collapse with isConstant?*/
|
||||
private ConstantDeclaration constantDeclaration;
|
||||
|
||||
/** Specifies that the variable must be aligned in memory. Only allowed for arrays & strings. [Only Variables in memory and arrays] */
|
||||
private Integer declaredAlignment;
|
||||
|
||||
@ -98,11 +101,6 @@ public class Variable implements Symbol {
|
||||
/** 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. [Only variables - not constants and not PHI masters] */
|
||||
private Registers.Register allocation;
|
||||
|
||||
/** Specifies whether the symbol is declared to be constant, never constant or maybe constant. */
|
||||
public enum ConstantDeclaration {
|
||||
CONST, NOT_CONST, MAYBE_CONST
|
||||
}
|
||||
|
||||
/** Memory area used for storing the variable (if is is stored in memory). */
|
||||
public enum MemoryArea {
|
||||
ZEROPAGE_MEMORY, MAIN_MEMORY
|
||||
@ -124,7 +122,6 @@ public class Variable implements Symbol {
|
||||
this.dataSegment = dataSegment;
|
||||
this.kind = Kind.CONSTANT;
|
||||
this.memoryArea = MemoryArea.MAIN_MEMORY;
|
||||
this.constantDeclaration = ConstantDeclaration.MAYBE_CONST;
|
||||
this.constantValue = value;
|
||||
this.inferredType = false;
|
||||
this.comments = new ArrayList<>();
|
||||
@ -148,7 +145,6 @@ public class Variable implements Symbol {
|
||||
this.dataSegment = dataSegment;
|
||||
this.kind = kind;
|
||||
this.memoryArea = memoryArea;
|
||||
this.constantDeclaration = ConstantDeclaration.MAYBE_CONST;
|
||||
if(Kind.PHI_MASTER.equals(kind))
|
||||
this.nextPhiVersionNumber = 0;
|
||||
this.inferredType = false;
|
||||
@ -168,7 +164,8 @@ public class Variable implements Symbol {
|
||||
this.setDeclaredAlignment(phiMaster.getDeclaredAlignment());
|
||||
this.setDeclaredAsRegister(phiMaster.isDeclaredAsRegister());
|
||||
this.setDeclaredNotRegister(phiMaster.isDeclaredAsNotRegister());
|
||||
this.setConstantDeclaration(phiMaster.getConstantDeclaration());
|
||||
this.setDeclaredConst(phiMaster.isDeclaredConst());
|
||||
this.setDeclaredNotConst(phiMaster.isDeclaredNotConst());
|
||||
this.setDeclaredRegister(phiMaster.getDeclaredRegister());
|
||||
this.setDeclaredVolatile(phiMaster.isDeclaredVolatile());
|
||||
this.setDeclaredExport(phiMaster.isDeclaredExport());
|
||||
@ -178,6 +175,7 @@ public class Variable implements Symbol {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Kind getKind() {
|
||||
return kind;
|
||||
}
|
||||
@ -357,20 +355,20 @@ public class Variable implements Symbol {
|
||||
}
|
||||
}
|
||||
|
||||
public void setConstantDeclaration(ConstantDeclaration constantDeclaration) {
|
||||
this.constantDeclaration = constantDeclaration;
|
||||
public boolean isDeclaredConst() {
|
||||
return declaredConst;
|
||||
}
|
||||
|
||||
public ConstantDeclaration getConstantDeclaration() {
|
||||
return constantDeclaration;
|
||||
public void setDeclaredConst(boolean declaredConst) {
|
||||
this.declaredConst = declaredConst;
|
||||
}
|
||||
|
||||
public boolean isDeclaredConstant() {
|
||||
return ConstantDeclaration.CONST.equals(constantDeclaration);
|
||||
public boolean isDeclaredNotConst() {
|
||||
return declaredNotConst;
|
||||
}
|
||||
|
||||
public boolean isDeclaredNotConstant() {
|
||||
return ConstantDeclaration.NOT_CONST.equals(constantDeclaration);
|
||||
public void setDeclaredNotConst(boolean declaredNotConst) {
|
||||
this.declaredNotConst = declaredNotConst;
|
||||
}
|
||||
|
||||
public Integer getDeclaredAlignment() {
|
||||
|
@ -622,7 +622,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
Variable lValue = getCurrentScope().addVariable(kind, varName, type, defaultMemoryArea, currentDataSegment);
|
||||
// Add directives
|
||||
directiveContext.applyDirectives(lValue, false, directives, new StatementSource(ctx));
|
||||
if(lValue.isDeclaredConstant()) {
|
||||
if(lValue.isDeclaredConst()) {
|
||||
// Add comments to constant
|
||||
lValue.setComments(ensureUnusedComments(comments));
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public class Pass1AssertNoConstParams extends Pass1Base {
|
||||
public boolean step() {
|
||||
for(Procedure procedure : getScope().getAllProcedures(true)) {
|
||||
for(Variable parameter : procedure.getParameters()) {
|
||||
if(parameter.isDeclaredConstant()) {
|
||||
if(parameter.isDeclaredConst()) {
|
||||
throw new CompileError("Error! Const parameters not supported "+parameter.getName()+" in "+ procedure.getFullName()+"()");
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
|
||||
Collection<SymbolVariableRef> earlyConstants = new ArrayList<>();
|
||||
for(Variable variable : getProgram().getScope().getAllVariables(true)) {
|
||||
SymbolVariableRef variableRef = variable.getRef();
|
||||
if(!variable.isDeclaredConstant() && !variable.isVolatile() && !variableRef.isIntermediate()) {
|
||||
if(variable.isDeclaredNotConstant())
|
||||
if(!variable.isDeclaredConst() && !variable.isVolatile() && !variableRef.isIntermediate()) {
|
||||
if(variable.isDeclaredNotConst())
|
||||
// Skip explicit non-constants
|
||||
continue;
|
||||
if(!isParameter(variableRef)) {
|
||||
|
@ -79,7 +79,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
||||
Collection<SymbolVariableRef> earlyIdentifiedConstants = getProgram().getEarlyIdentifiedConstants();
|
||||
Variable assignedVar = getScope().getVariable(lValueRef);
|
||||
if(assignedVar.isKindPhiMaster()) {
|
||||
if(assignedVar.isDeclaredConstant() || earlyIdentifiedConstants.contains(assignedVar.getRef()))
|
||||
if(assignedVar.isDeclaredConst() || earlyIdentifiedConstants.contains(assignedVar.getRef()))
|
||||
throw new InternalError("Error! Constants can not be versioned ", source);
|
||||
Variable version = assignedVar.createVersion();
|
||||
programLValue.set(version.getRef());
|
||||
@ -171,7 +171,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
||||
if(rValueVar.isKindPhiMaster()) {
|
||||
// rValue needs versioning - look for version in statements
|
||||
Variable rSymbol = rValueVar;
|
||||
if(rSymbol.isDeclaredConstant() || earlyIdentifiedConstants.contains(rSymbol.getRef())) {
|
||||
if(rSymbol.isDeclaredConst() || earlyIdentifiedConstants.contains(rSymbol.getRef())) {
|
||||
// A constant - find the single created version
|
||||
Scope scope = rSymbol.getScope();
|
||||
Collection<Variable> versions = scope.getVersions(rSymbol);
|
||||
|
@ -303,7 +303,8 @@ public class Pass1ProcedureInline extends Pass1Base {
|
||||
Variable inlineVar = callScope.addVariablePhiMaster(inlineVarName, procSymbol.getType(), procVar.getMemoryArea(), procVar.getDataSegment());
|
||||
inlineVar.setInferredType(procVar.isInferredType());
|
||||
inlineVar.setDeclaredAlignment(procVar.getDeclaredAlignment());
|
||||
inlineVar.setConstantDeclaration(procVar.getConstantDeclaration());
|
||||
inlineVar.setDeclaredConst(procVar.isDeclaredConst());
|
||||
inlineVar.setDeclaredNotConst(procVar.isDeclaredNotConst());
|
||||
inlineVar.setDeclaredAsRegister(procVar.isDeclaredAsRegister());
|
||||
inlineVar.setDeclaredNotRegister(procVar.isDeclaredAsNotRegister());
|
||||
inlineVar.setDeclaredRegister(procVar.getDeclaredRegister());
|
||||
|
@ -78,7 +78,8 @@ public class Pass1UnwindBlockScopes extends Pass1Base {
|
||||
Variable var = (Variable) symbol;
|
||||
Variable unwound = procedure.addVariablePhiMaster(name, symbol.getType(), var.getMemoryArea(), var.getDataSegment());
|
||||
unwound.setDeclaredAlignment(var.getDeclaredAlignment());
|
||||
unwound.setConstantDeclaration(var.getConstantDeclaration());
|
||||
unwound.setDeclaredConst(var.isDeclaredConst());
|
||||
unwound.setDeclaredNotConst((var.isDeclaredNotConst()));
|
||||
unwound.setDeclaredVolatile(var.isDeclaredVolatile());
|
||||
unwound.setInferredVolatile(var.isInferredVolatile());
|
||||
unwound.setDeclaredRegister((var.getDeclaredRegister()));
|
||||
|
@ -223,7 +223,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
}
|
||||
memberVariable.setDeclaredVolatile(variable.isDeclaredVolatile());
|
||||
memberVariable.setInferredVolatile(variable.isInferredVolatile());
|
||||
memberVariable.setConstantDeclaration(variable.getConstantDeclaration());
|
||||
memberVariable.setDeclaredConst(variable.isDeclaredConst());
|
||||
memberVariable.setDeclaredNotConst(variable.isDeclaredNotConst());
|
||||
memberVariable.setDeclaredExport(variable.isDeclaredExport());
|
||||
memberVariable.setKind(variable.getKind());
|
||||
if(memberVariable.getType() instanceof SymbolTypePointer) {
|
||||
|
@ -420,7 +420,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
String name;
|
||||
int score;
|
||||
Variable variable = scope.getVariable(var);
|
||||
if(variable.isDeclaredConstant() || variable.isKindConstant()) {
|
||||
if(variable.isDeclaredConst() || variable.isKindConstant()) {
|
||||
name = var.getFullNameUnversioned();
|
||||
score = 100;
|
||||
} else if(var.isVersion()) {
|
||||
|
@ -152,7 +152,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
if(lValue instanceof VariableRef) {
|
||||
VariableRef varRef = (VariableRef) lValue;
|
||||
Variable var = getScope().getVariable(varRef);
|
||||
if(var.isVolatile() || var.isDeclaredNotConstant() || var.isKindLoadStore())
|
||||
if(var.isVolatile() || var.isDeclaredNotConst() || var.isKindLoadStore())
|
||||
// Do not examine volatiles and non-versioned variables
|
||||
continue;
|
||||
ConstantValue constant = getConstant(assignment.getrValue2());
|
||||
@ -168,7 +168,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
if(getConstant(phiRValue.getrValue()) != null) {
|
||||
VariableRef varRef = phiVariable.getVariable();
|
||||
Variable var = getScope().getVariable(varRef);
|
||||
if(var.isVolatile() || var.isDeclaredNotConstant() || var.isKindLoadStore())
|
||||
if(var.isVolatile() || var.isDeclaredNotConst() || var.isKindLoadStore())
|
||||
// Do not examine volatiles and non-versioned variables
|
||||
continue;
|
||||
ConstantValue constant = getConstant(phiRValue.getrValue());
|
||||
@ -182,7 +182,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
|
||||
// Look for constants among non-versioned variables
|
||||
for(Variable variable : getScope().getAllVariables(true)) {
|
||||
if(variable.isVolatile() || variable.isDeclaredNotConstant() || !variable.isKindLoadStore())
|
||||
if(variable.isVolatile() || variable.isDeclaredNotConst() || !variable.isKindLoadStore())
|
||||
// Do not examine volatiles, non-constants or versioned variables
|
||||
continue;
|
||||
List<StatementLValue> assignments = getGraph().getAssignments(variable.getRef());
|
||||
|
@ -132,16 +132,6 @@ public class PassNTypeInference extends Pass2SsaOptimization {
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType()) || SymbolType.SNUMBER.equals(symbol.getType())) {
|
||||
SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment));
|
||||
setInferedType(program, assignment, symbol, type);
|
||||
// If the type is an array or a string the symbol is constant
|
||||
if(symbol.getType() instanceof SymbolTypeArray) {
|
||||
symbol.setConstantDeclaration(Variable.ConstantDeclaration.CONST);
|
||||
symbol.setKind(Variable.Kind.CONSTANT);
|
||||
symbol.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY);
|
||||
} else if(SymbolType.STRING.equals(symbol.getType())) {
|
||||
symbol.setConstantDeclaration(Variable.ConstantDeclaration.CONST);
|
||||
symbol.setKind(Variable.Kind.CONSTANT);
|
||||
symbol.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,11 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstDeclaration() throws IOException, URISyntaxException {
|
||||
compileAndCompare("const-declaration", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticRegisterOptimizationProblem() throws IOException, URISyntaxException {
|
||||
compileAndCompare("static-register-optimization-problem");
|
||||
|
17
src/test/kc/const-declaration.kc
Normal file
17
src/test/kc/const-declaration.kc
Normal file
@ -0,0 +1,17 @@
|
||||
// Tests a number of constant declarations
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
const char LINE_LEN = 40;
|
||||
const char MARGIN_TOP = 4;
|
||||
const char MARGIN_LEFT = 4;
|
||||
const unsigned int OFFSET = 40*5+5;
|
||||
const char* BODY1 = SCREEN+MARGIN_TOP*LINE_LEN+MARGIN_LEFT;
|
||||
const char* BODY2 = SCREEN+OFFSET;
|
||||
|
||||
void main() {
|
||||
*BODY1 = '*';
|
||||
*BODY2 = '*';
|
||||
}
|
||||
|
||||
|
||||
|
16
src/test/ref/const-declaration.asm
Normal file
16
src/test/ref/const-declaration.asm
Normal file
@ -0,0 +1,16 @@
|
||||
// Tests a number of constant declarations
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const LINE_LEN = $28
|
||||
.const MARGIN_TOP = 4
|
||||
.const MARGIN_LEFT = 4
|
||||
.const OFFSET = $28*5+5
|
||||
.label BODY2 = SCREEN+OFFSET
|
||||
main: {
|
||||
lda #'*'
|
||||
sta SCREEN+MARGIN_TOP*LINE_LEN+MARGIN_LEFT
|
||||
sta BODY2
|
||||
rts
|
||||
}
|
18
src/test/ref/const-declaration.cfg
Normal file
18
src/test/ref/const-declaration.cfg
Normal file
@ -0,0 +1,18 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((const byte*) SCREEN+(const byte) MARGIN_TOP*(const byte) LINE_LEN+(const byte) MARGIN_LEFT) ← (byte) '*'
|
||||
[5] *((const byte*) BODY2) ← (byte) '*'
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[6] return
|
||||
to:@return
|
315
src/test/ref/const-declaration.log
Normal file
315
src/test/ref/const-declaration.log
Normal file
@ -0,0 +1,315 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*) SCREEN ← ((byte*)) (number) $400
|
||||
(byte) LINE_LEN ← (number) $28
|
||||
(byte) MARGIN_TOP ← (number) 4
|
||||
(byte) MARGIN_LEFT ← (number) 4
|
||||
(word) OFFSET ← (number) $28*(number) 5+(number) 5
|
||||
(byte~) $0 ← (byte) MARGIN_TOP * (byte) LINE_LEN
|
||||
(byte*~) $1 ← (byte*) SCREEN + (byte~) $0
|
||||
(byte*~) $2 ← (byte*~) $1 + (byte) MARGIN_LEFT
|
||||
(byte*) BODY1 ← (byte*~) $2
|
||||
(byte*~) $3 ← (byte*) SCREEN + (word) OFFSET
|
||||
(byte*) BODY2 ← (byte*~) $3
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
*((byte*) BODY1) ← (byte) '*'
|
||||
*((byte*) BODY2) ← (byte) '*'
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(byte~) $0
|
||||
(byte*~) $1
|
||||
(byte*~) $2
|
||||
(byte*~) $3
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BODY1
|
||||
(byte*) BODY2
|
||||
(byte) LINE_LEN
|
||||
(byte) MARGIN_LEFT
|
||||
(byte) MARGIN_TOP
|
||||
(word) OFFSET
|
||||
(byte*) SCREEN
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
||||
Adding number conversion cast (unumber) $28 in (byte) LINE_LEN ← (number) $28
|
||||
Adding number conversion cast (unumber) 4 in (byte) MARGIN_TOP ← (number) 4
|
||||
Adding number conversion cast (unumber) 4 in (byte) MARGIN_LEFT ← (number) 4
|
||||
Adding number conversion cast (unumber) $28*5+5 in (word) OFFSET ← (number) $28*(number) 5+(number) 5
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte*) SCREEN ← (byte*)(number) $400
|
||||
Inlining cast (byte) LINE_LEN ← (unumber)(number) $28
|
||||
Inlining cast (byte) MARGIN_TOP ← (unumber)(number) 4
|
||||
Inlining cast (byte) MARGIN_LEFT ← (unumber)(number) 4
|
||||
Inlining cast (word) OFFSET ← (unumber)(number) $28*(number) 5+(number) 5
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast $28
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 4
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) $28
|
||||
Finalized unsigned number type (byte) 4
|
||||
Finalized unsigned number type (byte) 4
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte*) BODY1 = (byte*~) $2
|
||||
Alias (byte*) BODY2 = (byte*~) $3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Constant right-side identified [4] (word) OFFSET ← (unumber)(number) $28*(number) 5+(number) 5
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) SCREEN = (byte*) 1024
|
||||
Constant (const byte) LINE_LEN = $28
|
||||
Constant (const byte) MARGIN_TOP = 4
|
||||
Constant (const byte) MARGIN_LEFT = 4
|
||||
Constant (const word) OFFSET = (unumber)$28*5+5
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Converting *(pointer+n) to pointer[n] [11] *((byte*) BODY1) ← (byte) '*' -- *($1 + MARGIN_LEFT)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Eliminating unused variable (byte*) BODY1 and assignment [2] (byte*) BODY1 ← (byte*~) $1 + (const byte) MARGIN_LEFT
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant right-side identified [0] (byte~) $0 ← (const byte) MARGIN_TOP * (const byte) LINE_LEN
|
||||
Constant right-side identified [2] (byte*) BODY2 ← (const byte*) SCREEN + (const word) OFFSET
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) $0 = MARGIN_TOP*LINE_LEN
|
||||
Constant (const byte*) BODY2 = SCREEN+OFFSET
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant right-side identified [0] (byte*~) $1 ← (const byte*) SCREEN + (const byte) $0
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) $1 = SCREEN+$0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant inlined $0 = (const byte) MARGIN_TOP*(const byte) LINE_LEN
|
||||
Constant inlined $1 = (const byte*) SCREEN+(const byte) MARGIN_TOP*(const byte) LINE_LEN
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(SCREEN+MARGIN_TOP*LINE_LEN+MARGIN_LEFT)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] *((const byte*) SCREEN+(const byte) MARGIN_TOP*(const byte) LINE_LEN+(const byte) MARGIN_LEFT) ← (byte) '*'
|
||||
[5] *((const byte*) BODY2) ← (byte) '*'
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[6] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) main()
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Tests a number of constant declarations
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const LINE_LEN = $28
|
||||
.const MARGIN_TOP = 4
|
||||
.const MARGIN_LEFT = 4
|
||||
.const OFFSET = $28*5+5
|
||||
.label BODY2 = SCREEN+OFFSET
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [4] *((const byte*) SCREEN+(const byte) MARGIN_TOP*(const byte) LINE_LEN+(const byte) MARGIN_LEFT) ← (byte) '*' -- _deref_pbuc1=vbuc2
|
||||
lda #'*'
|
||||
sta SCREEN+MARGIN_TOP*LINE_LEN+MARGIN_LEFT
|
||||
// [5] *((const byte*) BODY2) ← (byte) '*' -- _deref_pbuc1=vbuc2
|
||||
lda #'*'
|
||||
sta BODY2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] *((const byte*) SCREEN+(const byte) MARGIN_TOP*(const byte) LINE_LEN+(const byte) MARGIN_LEFT) ← (byte) '*' [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] *((const byte*) BODY2) ← (byte) '*' [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 33 combination
|
||||
Uplifting [] best 33 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Tests a number of constant declarations
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const LINE_LEN = $28
|
||||
.const MARGIN_TOP = 4
|
||||
.const MARGIN_LEFT = 4
|
||||
.const OFFSET = $28*5+5
|
||||
.label BODY2 = SCREEN+OFFSET
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [4] *((const byte*) SCREEN+(const byte) MARGIN_TOP*(const byte) LINE_LEN+(const byte) MARGIN_LEFT) ← (byte) '*' -- _deref_pbuc1=vbuc2
|
||||
lda #'*'
|
||||
sta SCREEN+MARGIN_TOP*LINE_LEN+MARGIN_LEFT
|
||||
// [5] *((const byte*) BODY2) ← (byte) '*' -- _deref_pbuc1=vbuc2
|
||||
lda #'*'
|
||||
sta BODY2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #'*'
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label __bbegin with __b1
|
||||
Removing instruction __bbegin:
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction __b1:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) BODY2 = (const byte*) SCREEN+(const word) OFFSET
|
||||
(const byte) LINE_LEN = (byte) $28
|
||||
(const byte) MARGIN_LEFT = (byte) 4
|
||||
(const byte) MARGIN_TOP = (byte) 4
|
||||
(const word) OFFSET = (byte)(number) $28*(number) 5+(number) 5
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 16
|
||||
|
||||
// File Comments
|
||||
// Tests a number of constant declarations
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const LINE_LEN = $28
|
||||
.const MARGIN_TOP = 4
|
||||
.const MARGIN_LEFT = 4
|
||||
.const OFFSET = $28*5+5
|
||||
.label BODY2 = SCREEN+OFFSET
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// *BODY1 = '*'
|
||||
// [4] *((const byte*) SCREEN+(const byte) MARGIN_TOP*(const byte) LINE_LEN+(const byte) MARGIN_LEFT) ← (byte) '*' -- _deref_pbuc1=vbuc2
|
||||
lda #'*'
|
||||
sta SCREEN+MARGIN_TOP*LINE_LEN+MARGIN_LEFT
|
||||
// *BODY2 = '*'
|
||||
// [5] *((const byte*) BODY2) ← (byte) '*' -- _deref_pbuc1=vbuc2
|
||||
sta BODY2
|
||||
// main::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
12
src/test/ref/const-declaration.sym
Normal file
12
src/test/ref/const-declaration.sym
Normal file
@ -0,0 +1,12 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) BODY2 = (const byte*) SCREEN+(const word) OFFSET
|
||||
(const byte) LINE_LEN = (byte) $28
|
||||
(const byte) MARGIN_LEFT = (byte) 4
|
||||
(const byte) MARGIN_TOP = (byte) 4
|
||||
(const word) OFFSET = (byte)(number) $28*(number) 5+(number) 5
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
@ -30,8 +30,8 @@ main: scope:[main] from @9
|
||||
*((byte*) SPRITES_YPOS + (number) 0) ← (number) $64
|
||||
*((byte*) SPRITES_XPOS + (number) 0) ← (number) $64
|
||||
(byte*~) main::$0 ← (byte*) SCREEN + (word) SPRITE_PTRS
|
||||
(byte[$40]~) main::$1 ← (byte[$40]) SPRITE / (number) $40
|
||||
(byte~) main::$2 ← ((byte)) (byte[$40]~) main::$1
|
||||
(byte*~) main::$1 ← (byte[$40]) SPRITE / (number) $40
|
||||
(byte~) main::$2 ← ((byte)) (byte*~) main::$1
|
||||
*((byte*~) main::$0) ← (byte~) main::$2
|
||||
call saveZeropage
|
||||
to:main::@1
|
||||
@ -126,7 +126,7 @@ SYMBOL TABLE SSA
|
||||
(label) animSprite::@return
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(byte[$40]~) main::$1
|
||||
(byte*~) main::$1
|
||||
(byte~) main::$2
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
@ -146,7 +146,7 @@ Adding number conversion cast (unumber) $64 in *((byte*) SPRITES_YPOS + (number)
|
||||
Adding number conversion cast (unumber) 0 in *((byte*) SPRITES_YPOS + (number) 0) ← ((unumber)) (number) $64
|
||||
Adding number conversion cast (unumber) $64 in *((byte*) SPRITES_XPOS + (number) 0) ← (number) $64
|
||||
Adding number conversion cast (unumber) 0 in *((byte*) SPRITES_XPOS + (number) 0) ← ((unumber)) (number) $64
|
||||
Adding number conversion cast (unumber) $40 in (byte[$40]~) main::$1 ← (byte[$40]) SPRITE / (number) $40
|
||||
Adding number conversion cast (unumber) $40 in (byte*~) main::$1 ← (byte[$40]) SPRITE / (number) $40
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (word) SPRITE_PTRS ← (unumber)(number) $3f8
|
||||
Inlining cast (byte*) SPRITES_XPOS ← (byte*)(number) $d000
|
||||
@ -156,7 +156,7 @@ Inlining cast (byte*) SCREEN ← (byte*)(number) $400
|
||||
Inlining cast *((byte*) SPRITES_ENABLE) ← (unumber)(number) 1
|
||||
Inlining cast *((byte*) SPRITES_YPOS + (unumber)(number) 0) ← (unumber)(number) $64
|
||||
Inlining cast *((byte*) SPRITES_XPOS + (unumber)(number) 0) ← (unumber)(number) $64
|
||||
Inlining cast (byte~) main::$2 ← (byte)(byte[$40]~) main::$1
|
||||
Inlining cast (byte~) main::$2 ← (byte)(byte*~) main::$1
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast $3f8
|
||||
Simplifying constant pointer cast (byte*) 53248
|
||||
@ -195,10 +195,10 @@ Simplifying expression containing zero SPRITES_YPOS in [10] *((const byte*) SPRI
|
||||
Simplifying expression containing zero SPRITES_XPOS in [11] *((const byte*) SPRITES_XPOS + (byte) 0) ← (byte) $64
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Constant right-side identified [4] (byte*~) main::$0 ← (const byte*) SCREEN + (const word) SPRITE_PTRS
|
||||
Constant right-side identified [5] (byte[$40]~) main::$1 ← (const byte[$40]) SPRITE / (byte) $40
|
||||
Constant right-side identified [5] (byte*~) main::$1 ← (const byte[$40]) SPRITE / (byte) $40
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$0 = SCREEN+SPRITE_PTRS
|
||||
Constant (const byte[$40]) main::$1 = SPRITE/$40
|
||||
Constant (const byte*) main::$1 = SPRITE/$40
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const byte) main::$2 = (byte)main::$1
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
|
Loading…
x
Reference in New Issue
Block a user