diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java index 7979fb78c..00fa06cc5 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java @@ -1,5 +1,7 @@ package dk.camelot64.kickc.fragment; +import dk.camelot64.kickc.fragment.signature.AsmFragmentBindings; +import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature; import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; @@ -42,10 +44,10 @@ public class AsmFragmentInstanceSpec { * @param bindings Binding of named values in the fragment to values (constants, variables, ...) * @param codeScopeRef The scope containing the fragment. Used when referencing symbols defined in other scopes. */ - public AsmFragmentInstanceSpec(Program program, String signature, Map bindings, ScopeRef codeScopeRef) { + public AsmFragmentInstanceSpec(Program program, AsmFragmentSignature signature, AsmFragmentBindings bindings, ScopeRef codeScopeRef) { this.program = program; - this.signature = signature; - this.bindings = bindings; + this.signature = signature.getName(); + this.bindings = bindings.variables; this.codeScopeRef = codeScopeRef; } @@ -156,7 +158,7 @@ public class AsmFragmentInstanceSpec { SymbolType nextVariationValue = variationIterator.next(); // Find the next name String variationConstName = "c" + variationCurrentName.substring(variationCurrentName.length() - 1); - String variationNextName = AsmFragmentInstanceSpecBuilder.getTypePrefix(nextVariationValue) + variationConstName; + String variationNextName = AsmFragmentBindings.getTypePrefix(nextVariationValue) + variationConstName; // Update bindings Value constValue = bindings.get(variationCurrentName); bindings.remove(variationCurrentName); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java index 1436a6add..2e2231676 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.fragment; import dk.camelot64.kickc.asm.AsmFormat; +import dk.camelot64.kickc.fragment.signature.AsmFragmentBindings; import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature; import dk.camelot64.kickc.fragment.signature.AsmFragmentSignatureExpr; import dk.camelot64.kickc.model.*; @@ -12,33 +13,17 @@ import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.symbols.Variable; -import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.values.*; -import dk.camelot64.kickc.passes.utils.SizeOfConstants; - -import java.lang.InternalError; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; /** - * A fragment specification generated from a {@link Statement} used to load/synthesize an {@link AsmFragmentInstance} for creating ASM code for the statement + * Creates an ASM Fragment specification for a statement in the control flow graph. */ -public class AsmFragmentInstanceSpecBuilder { +final public class AsmFragmentInstanceSpecBuilder { - /** The symbol table. */ - private final Program program; - - /** Binding of named values in the fragment to values (constants, variables, ...). */ - private final Map bindings; - - /** The created ASM fragment instance specification. */ - private final AsmFragmentInstanceSpec asmFragmentInstanceSpec; - - /** Indexing for zeropages/constants/labels. */ - private int nextMemIdx = 1; - private int nextConstIdx = 1; - private int nextLabelIdx = 1; + private AsmFragmentInstanceSpecBuilder() { + } /** * Create a fragment instance spec factory for an indirect call. @@ -46,17 +31,12 @@ public class AsmFragmentInstanceSpecBuilder { * @return the fragment instance spec factory */ public static AsmFragmentInstanceSpec call(StatementCallExecute call, int indirectCallId, Program program) { - return new AsmFragmentInstanceSpecBuilder(call, indirectCallId, program).getAsmFragmentInstanceSpec(); - } - - private AsmFragmentInstanceSpecBuilder(StatementCallExecute call, int indirectCallId, Program program) { - this.program = program; - this.bindings = new LinkedHashMap<>(); + AsmFragmentBindings bindings = new AsmFragmentBindings(program); ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope(); - RValue procRVal = call.getProcedureRVal(); - AsmFragmentSignature signature = new AsmFragmentSignature.Call(bind(procRVal)); - bind("la1", new LabelRef(codeScope.getFullName() + "::" + "icall" + indirectCallId)); - this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature.getName(), bindings, codeScope); + RValue procedureRVal = call.getProcedureRVal(); + AsmFragmentSignature signature = new AsmFragmentSignature.Call(bindings.bind(procedureRVal)); + bindings.bind("la1", new LabelRef(codeScope.getFullName() + "::" + "icall" + indirectCallId)); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } /** @@ -67,11 +47,10 @@ public class AsmFragmentInstanceSpecBuilder { * @return the fragment instance spec factory */ public static AsmFragmentInstanceSpec interruptEntry(String interruptType, Program program) { - Map bindings = new HashMap<>(); - String signature = "isr_" + interruptType + "_entry"; + AsmFragmentBindings bindings = new AsmFragmentBindings(program); + AsmFragmentSignature signature = new AsmFragmentSignature.IsrEntry(interruptType); ScopeRef codeScope = program.getScope().getRef(); - final AsmFragmentInstanceSpec fragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); - return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec).getAsmFragmentInstanceSpec(); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } /** @@ -82,147 +61,94 @@ public class AsmFragmentInstanceSpecBuilder { * @return the fragment instance spec factory */ public static AsmFragmentInstanceSpec interruptExit(String interruptType, Program program) { - Map bindings = new HashMap<>(); - String signature = "isr_" + interruptType + "_exit"; + AsmFragmentBindings bindings = new AsmFragmentBindings(program); + AsmFragmentSignature signature = new AsmFragmentSignature.IsrExit(interruptType); ScopeRef codeScope = program.getScope().getRef(); - final AsmFragmentInstanceSpec fragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); - return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec).getAsmFragmentInstanceSpec(); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } - private AsmFragmentInstanceSpecBuilder(Program program, Map bindings, AsmFragmentInstanceSpec asmFragmentInstanceSpec) { - this.program = program; - this.bindings = bindings; - this.asmFragmentInstanceSpec = asmFragmentInstanceSpec; - } - - public static AsmFragmentInstanceSpec conditionalJump(StatementConditionalJump conditionalJump, ControlFlowBlock block, Program program) { - return new AsmFragmentInstanceSpecBuilder(conditionalJump, block, program).getAsmFragmentInstanceSpec(); - } - - private AsmFragmentInstanceSpecBuilder( - StatementConditionalJump conditionalJump, - ControlFlowBlock block, - Program program) { - this.program = program; - this.bindings = new LinkedHashMap<>(); + AsmFragmentBindings bindings = new AsmFragmentBindings(program); ScopeRef codeScope = program.getStatementInfos().getBlock(conditionalJump).getScope(); - String signature = conditionalJumpSignature(conditionalJump, block, program.getGraph()).getName(); - this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); + AsmFragmentSignature signature = conditionalJumpSignature(bindings, conditionalJump, block, program.getGraph()); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } public static AsmFragmentInstanceSpec exprSideEffect(StatementExprSideEffect exprSideEffect, Program program) { - return new AsmFragmentInstanceSpecBuilder(exprSideEffect, program).getAsmFragmentInstanceSpec(); - } - - private AsmFragmentInstanceSpecBuilder(StatementExprSideEffect exprSideEffect, Program program) { - this.program = program; - this.bindings = new LinkedHashMap<>(); + AsmFragmentBindings bindings = new AsmFragmentBindings(program); ScopeRef codeScope = program.getStatementInfos().getBlock(exprSideEffect).getScope(); - String signature = (new AsmFragmentSignature.ExprSideEffect(bind(exprSideEffect.getExpression()))).getName(); - this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); - } - - public static AsmFragmentInstanceSpec assignment(StatementAssignment assignment, Program program) { - return new AsmFragmentInstanceSpecBuilder(assignment, program).getAsmFragmentInstanceSpec(); + AsmFragmentSignature signature = new AsmFragmentSignature.ExprSideEffect(bindings.bind(exprSideEffect.getExpression())); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } /** * MAKELONG4() creates a long form 4 bytes * - * @param call The intrinsic call - * @param program The program + * @param make4long The intrinsic call + * @param program The program * @return The ASM fragment instance */ - public static AsmFragmentInstanceSpec makelong4(StatementCall call, Program program) { - return new AsmFragmentInstanceSpecBuilder(call, program).getAsmFragmentInstanceSpec(); - } - - private AsmFragmentInstanceSpecBuilder(StatementCall make4long, Program program) { - this.program = program; - this.bindings = new LinkedHashMap<>(); + public static AsmFragmentInstanceSpec makelong4(StatementCall make4long, Program program) { + AsmFragmentBindings bindings = new AsmFragmentBindings(program); if (make4long.getParameters().size() != 4) throw new CompileError("MAKELONG4() needs 4 parameters.", make4long); final AsmFragmentSignature.Assignment signature = new AsmFragmentSignature.Assignment( - bind(make4long.getlValue()), + bindings.bind(make4long.getlValue()), new AsmFragmentSignatureExpr.Makelong4( - bind(make4long.getParameter(3)), - bind(make4long.getParameter(2)), - bind(make4long.getParameter(1)), - bind(make4long.getParameter(0)) + bindings.bind(make4long.getParameter(3)), + bindings.bind(make4long.getParameter(2)), + bindings.bind(make4long.getParameter(1)), + bindings.bind(make4long.getParameter(0)) ) ); ScopeRef codeScope = program.getScope().getRef(); - this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature.getName(), bindings, codeScope); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } - private AsmFragmentInstanceSpecBuilder(StatementAssignment assignment, Program program) { - this.program = program; - this.bindings = new LinkedHashMap<>(); + public static AsmFragmentInstanceSpec assignment(StatementAssignment assignment, Program program) { + AsmFragmentBindings bindings = new AsmFragmentBindings(program); ScopeRef codeScope = program.getStatementInfos().getBlock(assignment).getScope(); - String signature = assignmentSignature( - assignment.getlValue(), - assignment.getrValue1(), - assignment.getOperator(), - assignment.getrValue2()); - this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); + final AsmFragmentSignatureExpr lValueExpr = bindings.bind(assignment.getlValue()); + final AsmFragmentSignatureExpr rValueExpr = assignmentRightSideSignature(bindings, assignment.getrValue1(), assignment.getOperator(), assignment.getrValue2()); + AsmFragmentSignature signature = new AsmFragmentSignature.Assignment(lValueExpr, rValueExpr); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } public static AsmFragmentInstanceSpec assignment(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) { - return new AsmFragmentInstanceSpecBuilder(lValue, rValue, program, codeScopeRef).getAsmFragmentInstanceSpec(); - } - - private AsmFragmentInstanceSpecBuilder(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) { - this.program = program; - this.bindings = new LinkedHashMap<>(); - String signature = assignmentSignature(lValue, null, null, rValue); - this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScopeRef); + AsmFragmentBindings bindings = new AsmFragmentBindings(program); + final AsmFragmentSignatureExpr lValueExpr = bindings.bind(lValue); + final AsmFragmentSignatureExpr rValueExpr = assignmentRightSideSignature(bindings, null, null, rValue); + AsmFragmentSignature signature = new AsmFragmentSignature.Assignment(lValueExpr, rValueExpr); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScopeRef); } public static AsmFragmentInstanceSpec assignmentAlu(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) { - return new AsmFragmentInstanceSpecBuilder(assignment, assignmentAlu, program).getAsmFragmentInstanceSpec(); - } - - private AsmFragmentInstanceSpecBuilder(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) { - this.program = program; - this.bindings = new LinkedHashMap<>(); + AsmFragmentBindings bindings = new AsmFragmentBindings(program); ScopeRef codeScope = program.getStatementInfos().getBlock(assignment).getScope(); - String signature = assignmentWithAluSignature(assignment, assignmentAlu).getName(); - this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); + AsmFragmentSignature signature = assignmentWithAluSignature(bindings, assignment, assignmentAlu); + return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } - public Map getBindings() { - return bindings; - } - - /** - * Get the created ASM fragment instance specification - * - * @return The ASM fragment instance specification - */ - public AsmFragmentInstanceSpec getAsmFragmentInstanceSpec() { - return asmFragmentInstanceSpec; - } - - private AsmFragmentSignature assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) { + private static AsmFragmentSignature assignmentWithAluSignature(AsmFragmentBindings bindingContext, StatementAssignment assignment, StatementAssignment assignmentAlu) { if (!(assignment.getrValue2() instanceof VariableRef)) { throw new AsmFragmentInstance.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment); } VariableRef assignmentRValue2 = (VariableRef) assignment.getrValue2(); - Variable assignmentRValue2Var = program.getSymbolInfos().getVariable(assignmentRValue2); + Variable assignmentRValue2Var = bindingContext.program.getSymbolInfos().getVariable(assignmentRValue2); Registers.Register rVal2Register = assignmentRValue2Var.getAllocation(); if (!rVal2Register.getType().equals(Registers.RegisterType.REG_ALU)) { throw new AsmFragmentInstance.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment); } - final AsmFragmentSignatureExpr lValueFragmentExpr = bind(assignment.getlValue()); + final AsmFragmentSignatureExpr lValueFragmentExpr = bindingContext.bind(assignment.getlValue()); AsmFragmentSignatureExpr rVal1FragmentExpr = null; if (assignment.getrValue1() != null) { - rVal1FragmentExpr = bind(assignment.getrValue1()); + rVal1FragmentExpr = bindingContext.bind(assignment.getrValue1()); } final AsmFragmentSignatureExpr rVal2FragmentExpr = assignmentRightSideSignature( + bindingContext, assignmentAlu.getrValue1(), assignmentAlu.getOperator(), assignmentAlu.getrValue2()); @@ -240,62 +166,43 @@ public class AsmFragmentInstanceSpecBuilder { } } - private String assignmentSignature(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) { - return (new AsmFragmentSignature.Assignment( - bind(lValue), - assignmentRightSideSignature(rValue1, operator, rValue2) - )).getName(); - } - - private AsmFragmentSignatureExpr assignmentRightSideSignature(RValue rValue1, Operator operator, RValue rValue2) { - - final SymbolType rValue1Type = rValue1 == null ? null : SymbolTypeInference.inferType(program.getScope(), rValue1); - + private static AsmFragmentSignatureExpr assignmentRightSideSignature(AsmFragmentBindings bindings, RValue rValue1, Operator operator, RValue rValue2) { + final SymbolType rValue1Type = rValue1 == null ? null : SymbolTypeInference.inferType(bindings.program.getScope(), rValue1); if (rValue1 == null && operator == null) { // Unmodified assignment - return bind(rValue2); + return bindings.bind(rValue2); } else if (rValue1 == null) { // Unary expression - return new AsmFragmentSignatureExpr.Unary((OperatorUnary) operator, bind(rValue2)); + return new AsmFragmentSignatureExpr.Unary((OperatorUnary) operator, bindings.bind(rValue2)); } else { - final AsmFragmentSignatureExpr rVal1SignatureExpr = bind(rValue1); + final AsmFragmentSignatureExpr rVal1SignatureExpr = bindings.bind(rValue1); // Binary expression AsmFragmentSignatureExpr rVal2SignatureExpr; - if ( - rValue2 instanceof ConstantInteger && - ((ConstantInteger) rValue2).getValue() == 1 && - (Operators.MINUS.equals(operator) || Operators.PLUS.equals(operator))) { + final boolean isMinusOrPlus = Operators.MINUS.equals(operator) || Operators.PLUS.equals(operator); + if (rValue2 instanceof ConstantInteger && ((ConstantInteger) rValue2).getValue() == 1 && isMinusOrPlus) { rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(1L)); - } else if ( - rValue2 instanceof ConstantInteger && - ((ConstantInteger) rValue2).getValue() == 2 && - (Operators.MINUS.equals(operator) || Operators.PLUS.equals(operator)) && - (SymbolType.BYTE.equals(rValue1Type) || SymbolType.SBYTE.equals(rValue1Type)) + } else if (rValue2 instanceof ConstantInteger && ((ConstantInteger) rValue2).getValue() == 2 && + isMinusOrPlus && (SymbolType.BYTE.equals(rValue1Type) || SymbolType.SBYTE.equals(rValue1Type)) ) { rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(2L)); - } else if ( - rValue2 instanceof ConstantInteger && - ((ConstantInteger) rValue2).getValue() <= 9 && - (Operators.SHIFT_RIGHT.equals(operator) || Operators.SHIFT_LEFT.equals(operator))) { - rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(((ConstantInteger) rValue2).getInteger())); - } else if ( - rValue2 instanceof ConstantInteger && - ((((ConstantInteger) rValue2).getValue()) % 8 == 0) && - (Operators.SHIFT_RIGHT.equals(operator) || Operators.SHIFT_LEFT.equals(operator))) { - rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(((ConstantInteger) rValue2).getInteger())); - } else if ( - rValue2 instanceof ConstantInteger && - ((ConstantInteger) rValue2).getValue() == 0 && - (Operators.MINUS.equals(operator) || Operators.PLUS.equals(operator))) { - rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(2L)); } else { - rVal2SignatureExpr = bind(rValue2); + final boolean isShift = Operators.SHIFT_RIGHT.equals(operator) || Operators.SHIFT_LEFT.equals(operator); + if (rValue2 instanceof ConstantInteger && ((ConstantInteger) rValue2).getValue() <= 9 && isShift) { + rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(((ConstantInteger) rValue2).getInteger())); + } else if (rValue2 instanceof ConstantInteger && ((((ConstantInteger) rValue2).getValue()) % 8 == 0) && isShift) { + rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(((ConstantInteger) rValue2).getInteger())); + } else if (rValue2 instanceof ConstantInteger && ((ConstantInteger) rValue2).getValue() == 0 && isMinusOrPlus) { + rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(2L)); + } else { + rVal2SignatureExpr = bindings.bind(rValue2); + } } return new AsmFragmentSignatureExpr.Binary((OperatorBinary) operator, rVal1SignatureExpr, rVal2SignatureExpr); } } - private AsmFragmentSignature conditionalJumpSignature( + private static AsmFragmentSignature conditionalJumpSignature( + AsmFragmentBindings bindings, StatementConditionalJump conditionalJump, ControlFlowBlock block, ControlFlowGraph graph) { @@ -303,14 +210,14 @@ public class AsmFragmentInstanceSpecBuilder { if (conditionalJump.getrValue1() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue1()).getValue() == 0) { rVal1SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(0L)); } else if (conditionalJump.getrValue1() != null) { - rVal1SignatureExpr = bind(conditionalJump.getrValue1()); + rVal1SignatureExpr = bindings.bind(conditionalJump.getrValue1()); } - AsmFragmentSignatureExpr rVal2SignatureExpr = null; + AsmFragmentSignatureExpr rVal2SignatureExpr; if (conditionalJump.getrValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue2()).getValue() == 0) { rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(0L)); } else { - rVal2SignatureExpr = bind(conditionalJump.getrValue2()); + rVal2SignatureExpr = bindings.bind(conditionalJump.getrValue2()); } AsmFragmentSignatureExpr condition; @@ -334,343 +241,9 @@ public class AsmFragmentInstanceSpecBuilder { } else { destinationLabel = destination.getLocalName(); } - Symbol destSymbol = program.getScope().getSymbol(destination); - final AsmFragmentSignatureExpr labelExpr = bind(new Label(destinationLabel, destSymbol.getScope(), false)); + Symbol destSymbol = bindings.program.getScope().getSymbol(destination); + final AsmFragmentSignatureExpr labelExpr = bindings.bind(new Label(destinationLabel, destSymbol.getScope(), false)); return new AsmFragmentSignature.ConditionalJump(condition, labelExpr); } - /** - * Add bindings of a value. - * - * @param value The value to bind. - * @return The bound name of the value. If the value has already been bound the existing bound name is returned. - */ - public AsmFragmentSignatureExpr bind(Value value) { - return bind(value, null); - } - - /** - * Add bindings of a value. - * - * @param value The value to bind. - * @param castType The type to bind the value as (used for casting). null if not casting, will use the actual type of the value. - * @return The bound name of the value. If the value has already been bound the existing bound name is returned. - */ - public AsmFragmentSignatureExpr bind(Value value, SymbolType castType) { - if (value instanceof CastValue) { - CastValue cast = (CastValue) value; - SymbolType toType = cast.getToType(); - RValue castValue = cast.getValue(); - SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue); - if (castValueType.getSizeBytes() == toType.getSizeBytes()) { - if (castType != null) { - if (castType.getSizeBytes() == toType.getSizeBytes()) { - return bind(castValue, castType); - } else { - OperatorUnary castUnary = Operators.getCastUnary(castType); - return new AsmFragmentSignatureExpr.Unary(castUnary, bind(castValue, toType)); - } - } else { - return bind(castValue, toType); - } - } else { - // Size of inner value and inner cast type mismatches - require explicit conversion - if (castType != null) { - OperatorUnary castUnaryInner = Operators.getCastUnary(toType); - OperatorUnary castUnaryOuter = Operators.getCastUnary(castType); - return new AsmFragmentSignatureExpr.Unary(castUnaryOuter, new AsmFragmentSignatureExpr.Unary(castUnaryInner, bind(castValue))); - } else { - OperatorUnary castUnaryInner = Operators.getCastUnary(toType); - return new AsmFragmentSignatureExpr.Unary(castUnaryInner, bind(castValue)); - } - } - } else if (value instanceof ConstantCastValue) { - ConstantCastValue castVal = (ConstantCastValue) value; - ConstantValue val = castVal.getValue(); - if (castType == null) { - SymbolType toType = castVal.getToType(); - // If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff ) - - if (toType instanceof SymbolTypeIntegerFixed) { - SymbolTypeIntegerFixed integerFixed = (SymbolTypeIntegerFixed) toType; - ConstantLiteral constantLiteral; - Long integerValue; - try { - constantLiteral = val.calculateLiteral(program.getScope()); - if (constantLiteral instanceof ConstantInteger) { - integerValue = ((ConstantInteger) constantLiteral).getValue(); - } else if (constantLiteral instanceof ConstantPointer) { - integerValue = ((ConstantPointer) constantLiteral).getValue(); - } else if (constantLiteral instanceof ConstantChar) { - integerValue = ((ConstantChar) constantLiteral).getInteger(); - } else { - throw new InternalError("Not implemented " + constantLiteral); - } - } catch (ConstantNotLiteral e) { - // Assume it is a word - integerValue = 0xffffL; - } - - if (!integerFixed.contains(integerValue)) { - if (toType.getSizeBytes() == 1) { - val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val); - } else if (toType.getSizeBytes() == 2) { - val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val); - } else if (toType.getSizeBytes() == 4) { - val = new ConstantBinary(new ConstantInteger(0xffffffffL, SymbolType.DWORD), Operators.BOOL_AND, val); - } else { - throw new InternalError("Not implemented " + toType); - } - } - } - - return bind(val, toType); - } else { - return bind(val, castType); - } - } else if (value instanceof PointerDereference) { - PointerDereference deref = (PointerDereference) value; - SymbolType ptrType = null; - if (castType != null) { - ptrType = new SymbolTypePointer(castType); - } - if (value instanceof PointerDereferenceSimple) { - final AsmFragmentSignatureExpr bindPointer = bind(deref.getPointer(), ptrType); - return new AsmFragmentSignatureExpr.DerefSimple(bindPointer); - } else if (value instanceof PointerDereferenceIndexed) { - PointerDereferenceIndexed derefIdx = (PointerDereferenceIndexed) value; - final AsmFragmentSignatureExpr bindPointer = bind(derefIdx.getPointer(), ptrType); - final AsmFragmentSignatureExpr bindIndex = bind(derefIdx.getIndex()); - return new AsmFragmentSignatureExpr.DerefIdx(bindPointer, bindIndex); - } - } else if (value instanceof VariableRef) { - Variable variable = program.getSymbolInfos().getVariable((VariableRef) value); - if (castType == null) { - castType = variable.getType(); - } - Registers.Register register = variable.getAllocation(); - String name = getTypePrefix(castType) + getRegisterName(register); - bind(name, variable); - return new AsmFragmentSignatureExpr.Variable(name, castType); - } else if (value instanceof ConstantValue) { - if (castType == null) { - castType = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value); - } - String name = getTypePrefix(castType) + getConstName(value); - bind(name, value); - return new AsmFragmentSignatureExpr.Variable(name, castType); - } else if (value instanceof ProcedureRef) { - if (castType == null) { - castType = SymbolTypeInference.inferType(program.getScope(), (ProcedureRef) value); - } - String name = getTypePrefix(castType) + getConstName(value); - bind(name, value); - return new AsmFragmentSignatureExpr.Variable(name, castType); - } else if (value instanceof Label) { - String name = "la" + nextLabelIdx++; - bind(name, value); - return new AsmFragmentSignatureExpr.Variable(name, SymbolType.LABEL); - } else if (value instanceof StackIdxValue) { - StackIdxValue stackIdxValue = (StackIdxValue) value; - return new AsmFragmentSignatureExpr.StackIdx( - stackIdxValue.getValueType(), - bindStructSize(stackIdxValue.getValueType()), - bind(stackIdxValue.getStackOffset())); - } else if (value instanceof StackPushValue) { - final StackPushValue stackPushValue = (StackPushValue) value; - return new AsmFragmentSignatureExpr.StackPush(stackPushValue.getType(), bindStructSize(stackPushValue.getType())); - } else if (value instanceof StackPullValue) { - final StackPullValue stackPullValue = (StackPullValue) value; - return new AsmFragmentSignatureExpr.StackPull(stackPullValue.getType(), bindStructSize(stackPullValue.getType())); - } else if (value instanceof StackPullBytes) { - final ConstantInteger bytes = (ConstantInteger) ((StackPullBytes) value).getBytes(); - return new AsmFragmentSignatureExpr.StackPullPadding(bytes); - } else if (value instanceof StackPushBytes) { - final ConstantInteger bytes = (ConstantInteger) ((StackPushBytes) value).getBytes(); - return new AsmFragmentSignatureExpr.StackPushPadding(bytes); - } else if (value instanceof MemsetValue) { - MemsetValue memsetValue = (MemsetValue) value; - ConstantValue sizeConst = memsetValue.getSize(); - if (sizeConst.getType(program.getScope()).equals(SymbolType.NUMBER)) { - SymbolType fixedIntegerType = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(sizeConst, program.getScope()); - sizeConst = new ConstantCastValue(fixedIntegerType, sizeConst); - } - return new AsmFragmentSignatureExpr.Memset(bind(sizeConst)); - } else if (value instanceof MemcpyValue) { - MemcpyValue memcpyValue = (MemcpyValue) value; - ConstantValue sizeConst = memcpyValue.getSize(); - if (sizeConst.getType(program.getScope()).equals(SymbolType.NUMBER)) { - SymbolType fixedIntegerType = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(sizeConst, program.getScope()); - sizeConst = new ConstantCastValue(fixedIntegerType, sizeConst); - } - return new AsmFragmentSignatureExpr.Memcpy(bind(memcpyValue.getSource()), bind(sizeConst)); - } - throw new RuntimeException("Binding of value type not supported " + value.toString(program)); - } - - /** - * Binds the struct size (if the type is a struct.) - * - * @param type The type - * @return The signature. null if the type is not a struct. - */ - private AsmFragmentSignatureExpr bindStructSize(SymbolType type) { - if (type instanceof SymbolTypeStruct) { - ConstantRef sizeConst = SizeOfConstants.getSizeOfConstantVar(program.getScope(), type); - ConstantLiteral literal = sizeConst.calculateLiteral(program.getScope()); - if (literal instanceof ConstantInteger && ((ConstantInteger) literal).getInteger() <= 4L) - return new AsmFragmentSignatureExpr.Number((ConstantInteger) literal); - else - return bind(sizeConst); - } - return null; - } - - /** - * Add binding for a name/value pair if it is not already bound. - * - * @param name The name - * @param value The value - */ - private void bind(String name, Value value) { - bindings.putIfAbsent(name, value); - } - - /** - * Get the symbol type part of the binding name (eg. vbu/pws/...) - * - * @param type The type - * @return The type name - */ - static String getTypePrefix(SymbolType type) { - if (type instanceof SymbolTypePointer) { - SymbolType elmType = ((SymbolTypePointer) type).getElementType(); - if (elmType instanceof SymbolTypePointer) { - SymbolType eml2Type = ((SymbolTypePointer) elmType).getElementType(); - if (eml2Type instanceof SymbolTypePointer) { - throw new RuntimeException("Not implemented " + type); - } else { - return "q" + getBaseTypePrefix(eml2Type); - } - } else { - return "p" + getBaseTypePrefix(elmType); - } - } else { - return "v" + getBaseTypePrefix(type); - } - } - - /** - * Get the base symbol type part of the binding name (eg. bu/ws/...). - * This only handles basic types (not pointers) - * - * @param baseType The basic type - * @return The 2-letter base type name (eg. bu/ws/...). - */ - static String getBaseTypePrefix(SymbolType baseType) { - if (SymbolType.BYTE.equals(baseType)) { - return "bu"; - } else if (SymbolType.SBYTE.equals(baseType)) { - return "bs"; - } else if (SymbolType.WORD.equals(baseType)) { - return "wu"; - } else if (SymbolType.SWORD.equals(baseType)) { - return "ws"; - } else if (SymbolType.DWORD.equals(baseType)) { - return "du"; - } else if (SymbolType.SDWORD.equals(baseType)) { - return "ds"; - } else if (SymbolType.VOID.equals(baseType)) { - return "vo"; - } else if (SymbolType.BOOLEAN.equals(baseType)) { - return "bo"; - } else if (baseType instanceof SymbolTypeStruct) { - return "ss"; - } else if (baseType instanceof SymbolTypeProcedure) { - return "pr"; - } else { - throw new CompileError("Type not supported in fragments " + baseType); - } - } - - /** - * Get the register part of the binding name (eg. aa, z1, z2, ...). - * Examines all previous bindings to reuse register index if the same register is bound multiple times. - * - * @param register The register - * @return The register part of the binding name. - */ - private String getRegisterName(Registers.Register register) { - if (Registers.RegisterType.ZP_MEM.equals(register.getType())) { - // Examine if the ZP register is already bound - Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) register; - String memNameIdx = null; - for (String boundName : bindings.keySet()) { - Value boundValue = bindings.get(boundName); - if (boundValue instanceof Variable && ((Variable) boundValue).isVariable()) { - Variable boundVariable = (Variable) boundValue; - Registers.Register boundRegister = boundVariable.getAllocation(); - if (boundRegister != null && Registers.RegisterType.ZP_MEM.equals(boundRegister.getType())) { - Registers.RegisterZpMem boundRegisterZp = (Registers.RegisterZpMem) boundRegister; - if (registerZp.getZp() == boundRegisterZp.getZp()) { - // Found other register with same ZP address! - memNameIdx = boundName.substring(boundName.length() - 1); - break; - } - } - } - } - // If not create a new one - if (memNameIdx == null) { - memNameIdx = Integer.toString(nextMemIdx++); - } - return "z" + memNameIdx; - } else if (Registers.RegisterType.MAIN_MEM.equals(register.getType())) { - String memNameIdx = null; - for (String boundName : bindings.keySet()) { - Value boundValue = bindings.get(boundName); - if (boundValue instanceof Variable && ((Variable) boundValue).isVariable()) { - Variable boundVariable = (Variable) boundValue; - Registers.Register boundRegister = boundVariable.getAllocation(); - if (boundRegister instanceof Registers.RegisterMainMem) { - if (boundRegister.equals(register)) { - memNameIdx = boundName.substring(boundName.length() - 1); - break; - } - } - } - } - if (memNameIdx == null) { - memNameIdx = Integer.toString(nextMemIdx++); - } - return "m" + memNameIdx; - } else if (Registers.RegisterType.REG_A.equals(register.getType())) { - return "aa"; - } else if (Registers.RegisterType.REG_X.equals(register.getType())) { - return "xx"; - } else if (Registers.RegisterType.REG_Y.equals(register.getType())) { - return "yy"; - } else if (Registers.RegisterType.REG_Z.equals(register.getType())) { - return "zz"; - } else if (Registers.RegisterType.REG_ALU.equals(register.getType())) { - throw new AsmFragmentInstance.AluNotApplicableException(); - } else { - throw new RuntimeException("Not implemented " + register.getType()); - } - } - - private String getConstName(Value constant) { - // If the constant is already bound - reuse the index - for (String boundName : bindings.keySet()) { - Value boundValue = bindings.get(boundName); - if (boundValue instanceof ConstantValue || (boundValue instanceof Variable && ((Variable) boundValue).isKindConstant())) { - if (boundValue.equals(constant)) { - return "c" + boundName.substring(boundName.length() - 1); - } - } - } - // Otherwise use a new index - return "c" + nextConstIdx++; - } - } \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentBindings.java b/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentBindings.java new file mode 100644 index 000000000..85bf58a15 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentBindings.java @@ -0,0 +1,380 @@ +package dk.camelot64.kickc.fragment.signature; + +import dk.camelot64.kickc.fragment.AsmFragmentInstance; +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ConstantNotLiteral; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.Registers; +import dk.camelot64.kickc.model.operators.OperatorUnary; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.symbols.Label; +import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.types.*; +import dk.camelot64.kickc.model.values.*; +import dk.camelot64.kickc.passes.utils.SizeOfConstants; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Used to create variable bindings for ASM fragments. + */ +public class AsmFragmentBindings { + + public AsmFragmentBindings(Program program) { + this.program = program; + this.variables = new LinkedHashMap<>(); + } + + /** + * The program. + */ + public final Program program; + + /** + * Binding of named values in the fragment to values (constants, variables, ...). + */ + public final Map variables; + + /** + * Indexing for zeropages/constants/labels. + */ + private int nextMemIdx = 1; + private int nextConstIdx = 1; + private int nextLabelIdx = 1; + + /** + * Get the symbol type part of the binding name (eg. vbu/pws/...) + * + * @param type The type + * @return The type name + */ + public static String getTypePrefix(SymbolType type) { + if (type instanceof SymbolTypePointer) { + SymbolType elmType = ((SymbolTypePointer) type).getElementType(); + if (elmType instanceof SymbolTypePointer) { + SymbolType eml2Type = ((SymbolTypePointer) elmType).getElementType(); + if (eml2Type instanceof SymbolTypePointer) { + throw new RuntimeException("Not implemented " + type); + } else { + return "q" + getBaseTypePrefix(eml2Type); + } + } else { + return "p" + getBaseTypePrefix(elmType); + } + } else { + return "v" + getBaseTypePrefix(type); + } + } + + /** + * Get the base symbol type part of the binding name (eg. bu/ws/...). + * This only handles basic types (not pointers) + * + * @param baseType The basic type + * @return The 2-letter base type name (eg. bu/ws/...). + */ + static String getBaseTypePrefix(SymbolType baseType) { + if (SymbolType.BYTE.equals(baseType)) { + return "bu"; + } else if (SymbolType.SBYTE.equals(baseType)) { + return "bs"; + } else if (SymbolType.WORD.equals(baseType)) { + return "wu"; + } else if (SymbolType.SWORD.equals(baseType)) { + return "ws"; + } else if (SymbolType.DWORD.equals(baseType)) { + return "du"; + } else if (SymbolType.SDWORD.equals(baseType)) { + return "ds"; + } else if (SymbolType.VOID.equals(baseType)) { + return "vo"; + } else if (SymbolType.BOOLEAN.equals(baseType)) { + return "bo"; + } else if (baseType instanceof SymbolTypeStruct) { + return "ss"; + } else if (baseType instanceof SymbolTypeProcedure) { + return "pr"; + } else { + throw new CompileError("Type not supported in fragments " + baseType); + } + } + + /** + * Add bindings of a value. + * + * @param value The value to bind. + * @return The bound name of the value. If the value has already been bound the existing bound name is returned. + */ + public AsmFragmentSignatureExpr bind(Value value) { + return bind(value, null); + } + + /** + * Binds the struct size (if the type is a struct.) + * + * @param type The type + * @return The signature. null if the type is not a struct. + */ + private AsmFragmentSignatureExpr bindStructSize(SymbolType type) { + if (type instanceof SymbolTypeStruct) { + ConstantRef sizeConst = SizeOfConstants.getSizeOfConstantVar(program.getScope(), type); + ConstantLiteral literal = sizeConst.calculateLiteral(program.getScope()); + if (literal instanceof ConstantInteger && ((ConstantInteger) literal).getInteger() <= 4L) + return new AsmFragmentSignatureExpr.Number((ConstantInteger) literal); + else + return this.bind(sizeConst); + } + return null; + } + + /** + * Get the register part of the binding name (eg. aa, z1, z2, ...). + * Examines all previous bindings to reuse register index if the same register is bound multiple times. + * + * @param register The register + * @return The register part of the binding name. + */ + private String getRegisterName(Registers.Register register) { + if (Registers.RegisterType.ZP_MEM.equals(register.getType())) { + // Examine if the ZP register is already bound + Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) register; + String memNameIdx = null; + for (String boundName : variables.keySet()) { + Value boundValue = variables.get(boundName); + if (boundValue instanceof Variable && ((Variable) boundValue).isVariable()) { + Variable boundVariable = (Variable) boundValue; + Registers.Register boundRegister = boundVariable.getAllocation(); + if (boundRegister != null && Registers.RegisterType.ZP_MEM.equals(boundRegister.getType())) { + Registers.RegisterZpMem boundRegisterZp = (Registers.RegisterZpMem) boundRegister; + if (registerZp.getZp() == boundRegisterZp.getZp()) { + // Found other register with same ZP address! + memNameIdx = boundName.substring(boundName.length() - 1); + break; + } + } + } + } + // If not create a new one + if (memNameIdx == null) { + memNameIdx = Integer.toString(nextMemIdx++); + } + return "z" + memNameIdx; + } else if (Registers.RegisterType.MAIN_MEM.equals(register.getType())) { + String memNameIdx = null; + for (String boundName : variables.keySet()) { + Value boundValue = variables.get(boundName); + if (boundValue instanceof Variable && ((Variable) boundValue).isVariable()) { + Variable boundVariable = (Variable) boundValue; + Registers.Register boundRegister = boundVariable.getAllocation(); + if (boundRegister instanceof Registers.RegisterMainMem) { + if (boundRegister.equals(register)) { + memNameIdx = boundName.substring(boundName.length() - 1); + break; + } + } + } + } + if (memNameIdx == null) { + memNameIdx = Integer.toString(nextMemIdx++); + } + return "m" + memNameIdx; + } else if (Registers.RegisterType.REG_A.equals(register.getType())) { + return "aa"; + } else if (Registers.RegisterType.REG_X.equals(register.getType())) { + return "xx"; + } else if (Registers.RegisterType.REG_Y.equals(register.getType())) { + return "yy"; + } else if (Registers.RegisterType.REG_Z.equals(register.getType())) { + return "zz"; + } else if (Registers.RegisterType.REG_ALU.equals(register.getType())) { + throw new AsmFragmentInstance.AluNotApplicableException(); + } else { + throw new RuntimeException("Not implemented " + register.getType()); + } + } + + private String getConstName(Value constant) { + // If the constant is already bound - reuse the index + for (String boundName : variables.keySet()) { + Value boundValue = variables.get(boundName); + if (boundValue instanceof ConstantValue || (boundValue instanceof Variable && ((Variable) boundValue).isKindConstant())) { + if (boundValue.equals(constant)) { + return "c" + boundName.substring(boundName.length() - 1); + } + } + } + // Otherwise use a new index + return "c" + nextConstIdx++; + } + + /** + * Add bindings of a value. + * + * @param value The value to bind. + * @param castType The type to bind the value as (used for casting). null if not casting, will use the actual type of the value. + * @return The bound name of the value. If the value has already been bound the existing bound name is returned. + */ + public AsmFragmentSignatureExpr bind(Value value, SymbolType castType) { + if (value instanceof CastValue) { + CastValue cast = (CastValue) value; + SymbolType toType = cast.getToType(); + RValue castValue = cast.getValue(); + SymbolType castValueType = SymbolTypeInference.inferType(program.getScope(), castValue); + if (castValueType.getSizeBytes() == toType.getSizeBytes()) { + if (castType != null) { + if (castType.getSizeBytes() == toType.getSizeBytes()) { + return this.bind(castValue, castType); + } else { + OperatorUnary castUnary = Operators.getCastUnary(castType); + return new AsmFragmentSignatureExpr.Unary(castUnary, this.bind(castValue, toType)); + } + } else { + return this.bind(castValue, toType); + } + } else { + // Size of inner value and inner cast type mismatches - require explicit conversion + if (castType != null) { + OperatorUnary castUnaryInner = Operators.getCastUnary(toType); + OperatorUnary castUnaryOuter = Operators.getCastUnary(castType); + return new AsmFragmentSignatureExpr.Unary(castUnaryOuter, new AsmFragmentSignatureExpr.Unary(castUnaryInner, this.bind(castValue))); + } else { + OperatorUnary castUnaryInner = Operators.getCastUnary(toType); + return new AsmFragmentSignatureExpr.Unary(castUnaryInner, this.bind(castValue)); + } + } + } else if (value instanceof ConstantCastValue) { + ConstantCastValue castVal = (ConstantCastValue) value; + ConstantValue val = castVal.getValue(); + if (castType == null) { + SymbolType toType = castVal.getToType(); + // If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff ) + + if (toType instanceof SymbolTypeIntegerFixed) { + SymbolTypeIntegerFixed integerFixed = (SymbolTypeIntegerFixed) toType; + ConstantLiteral constantLiteral; + Long integerValue; + try { + constantLiteral = val.calculateLiteral(program.getScope()); + if (constantLiteral instanceof ConstantInteger) { + integerValue = ((ConstantInteger) constantLiteral).getValue(); + } else if (constantLiteral instanceof ConstantPointer) { + integerValue = ((ConstantPointer) constantLiteral).getValue(); + } else if (constantLiteral instanceof ConstantChar) { + integerValue = ((ConstantChar) constantLiteral).getInteger(); + } else { + throw new InternalError("Not implemented " + constantLiteral); + } + } catch (ConstantNotLiteral e) { + // Assume it is a word + integerValue = 0xffffL; + } + + if (!integerFixed.contains(integerValue)) { + if (toType.getSizeBytes() == 1) { + val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val); + } else if (toType.getSizeBytes() == 2) { + val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val); + } else if (toType.getSizeBytes() == 4) { + val = new ConstantBinary(new ConstantInteger(0xffffffffL, SymbolType.DWORD), Operators.BOOL_AND, val); + } else { + throw new InternalError("Not implemented " + toType); + } + } + } + + return this.bind(val, toType); + } else { + return this.bind(val, castType); + } + } else if (value instanceof PointerDereference) { + PointerDereference deref = (PointerDereference) value; + SymbolType ptrType = null; + if (castType != null) { + ptrType = new SymbolTypePointer(castType); + } + if (value instanceof PointerDereferenceSimple) { + final AsmFragmentSignatureExpr bindPointer = this.bind(deref.getPointer(), ptrType); + return new AsmFragmentSignatureExpr.DerefSimple(bindPointer); + } else if (value instanceof PointerDereferenceIndexed) { + PointerDereferenceIndexed derefIdx = (PointerDereferenceIndexed) value; + final AsmFragmentSignatureExpr bindPointer = this.bind(derefIdx.getPointer(), ptrType); + final AsmFragmentSignatureExpr bindIndex = this.bind(derefIdx.getIndex()); + return new AsmFragmentSignatureExpr.DerefIdx(bindPointer, bindIndex); + } + } else if (value instanceof VariableRef) { + Variable variable = program.getSymbolInfos().getVariable((VariableRef) value); + if (castType == null) { + castType = variable.getType(); + } + Registers.Register register = variable.getAllocation(); + String name = getTypePrefix(castType) + this.getRegisterName(register); + bind(name, variable); + return new AsmFragmentSignatureExpr.Variable(name, castType); + } else if (value instanceof ConstantValue) { + if (castType == null) { + castType = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value); + } + String name = getTypePrefix(castType) + this.getConstName(value); + bind(name, value); + return new AsmFragmentSignatureExpr.Variable(name, castType); + } else if (value instanceof ProcedureRef) { + if (castType == null) { + castType = SymbolTypeInference.inferType(program.getScope(), (ProcedureRef) value); + } + String name = getTypePrefix(castType) + this.getConstName(value); + bind(name, value); + return new AsmFragmentSignatureExpr.Variable(name, castType); + } else if (value instanceof Label) { + String name = "la" + nextLabelIdx++; + bind(name, value); + return new AsmFragmentSignatureExpr.Variable(name, SymbolType.LABEL); + } else if (value instanceof StackIdxValue) { + StackIdxValue stackIdxValue = (StackIdxValue) value; + return new AsmFragmentSignatureExpr.StackIdx( + stackIdxValue.getValueType(), + this.bindStructSize(stackIdxValue.getValueType()), + this.bind(stackIdxValue.getStackOffset())); + } else if (value instanceof StackPushValue) { + final StackPushValue stackPushValue = (StackPushValue) value; + return new AsmFragmentSignatureExpr.StackPush(stackPushValue.getType(), this.bindStructSize(stackPushValue.getType())); + } else if (value instanceof StackPullValue) { + final StackPullValue stackPullValue = (StackPullValue) value; + return new AsmFragmentSignatureExpr.StackPull(stackPullValue.getType(), this.bindStructSize(stackPullValue.getType())); + } else if (value instanceof StackPullBytes) { + final ConstantInteger bytes = (ConstantInteger) ((StackPullBytes) value).getBytes(); + return new AsmFragmentSignatureExpr.StackPullPadding(bytes); + } else if (value instanceof StackPushBytes) { + final ConstantInteger bytes = (ConstantInteger) ((StackPushBytes) value).getBytes(); + return new AsmFragmentSignatureExpr.StackPushPadding(bytes); + } else if (value instanceof MemsetValue) { + MemsetValue memsetValue = (MemsetValue) value; + ConstantValue sizeConst = memsetValue.getSize(); + if (sizeConst.getType(program.getScope()).equals(SymbolType.NUMBER)) { + SymbolType fixedIntegerType = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(sizeConst, program.getScope()); + sizeConst = new ConstantCastValue(fixedIntegerType, sizeConst); + } + return new AsmFragmentSignatureExpr.Memset(this.bind(sizeConst)); + } else if (value instanceof MemcpyValue) { + MemcpyValue memcpyValue = (MemcpyValue) value; + ConstantValue sizeConst = memcpyValue.getSize(); + if (sizeConst.getType(program.getScope()).equals(SymbolType.NUMBER)) { + SymbolType fixedIntegerType = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(sizeConst, program.getScope()); + sizeConst = new ConstantCastValue(fixedIntegerType, sizeConst); + } + return new AsmFragmentSignatureExpr.Memcpy(this.bind(memcpyValue.getSource()), this.bind(sizeConst)); + } + throw new RuntimeException("Binding of value type not supported " + value.toString(program)); + } + + /** + * Add binding for a name/value pair if it is not already bound. + * + * @param name The name + * @param value The value + */ + public void bind(String name, Value value) { + variables.putIfAbsent(name, value); + } + +} diff --git a/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java b/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java index fb26092df..444d92fdf 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java +++ b/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java @@ -85,4 +85,34 @@ public interface AsmFragmentSignature { return expr.getName(); } } + + /** Interrupt Service Routine Entry Code. */ + class IsrEntry implements AsmFragmentSignature { + + final private String interruptType; + + public IsrEntry(String interruptType) { + this.interruptType = interruptType; + } + + @Override + public String getName() { + return "isr_" + interruptType + "_entry"; + } + } + + /** Interrupt Service Routine Exit Code. */ + class IsrExit implements AsmFragmentSignature { + + final private String interruptType; + + public IsrExit(String interruptType) { + this.interruptType = interruptType; + } + + @Override + public String getName() { + return "isr_" + interruptType + "_exit"; + } + } }