mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-26 18:29:54 +00:00
Refactored ASM fragment bindings into separate class.
This commit is contained in:
parent
9c1886d18f
commit
87cc51d685
@ -1,5 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
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.ConstantNotLiteral;
|
||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
import dk.camelot64.kickc.model.statements.Statement;
|
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 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.
|
* @param codeScopeRef The scope containing the fragment. Used when referencing symbols defined in other scopes.
|
||||||
*/
|
*/
|
||||||
public AsmFragmentInstanceSpec(Program program, String signature, Map<String, Value> bindings, ScopeRef codeScopeRef) {
|
public AsmFragmentInstanceSpec(Program program, AsmFragmentSignature signature, AsmFragmentBindings bindings, ScopeRef codeScopeRef) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.signature = signature;
|
this.signature = signature.getName();
|
||||||
this.bindings = bindings;
|
this.bindings = bindings.variables;
|
||||||
this.codeScopeRef = codeScopeRef;
|
this.codeScopeRef = codeScopeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +158,7 @@ public class AsmFragmentInstanceSpec {
|
|||||||
SymbolType nextVariationValue = variationIterator.next();
|
SymbolType nextVariationValue = variationIterator.next();
|
||||||
// Find the next name
|
// Find the next name
|
||||||
String variationConstName = "c" + variationCurrentName.substring(variationCurrentName.length() - 1);
|
String variationConstName = "c" + variationCurrentName.substring(variationCurrentName.length() - 1);
|
||||||
String variationNextName = AsmFragmentInstanceSpecBuilder.getTypePrefix(nextVariationValue) + variationConstName;
|
String variationNextName = AsmFragmentBindings.getTypePrefix(nextVariationValue) + variationConstName;
|
||||||
// Update bindings
|
// Update bindings
|
||||||
Value constValue = bindings.get(variationCurrentName);
|
Value constValue = bindings.get(variationCurrentName);
|
||||||
bindings.remove(variationCurrentName);
|
bindings.remove(variationCurrentName);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
package dk.camelot64.kickc.fragment;
|
||||||
|
|
||||||
import dk.camelot64.kickc.asm.AsmFormat;
|
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.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignatureExpr;
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignatureExpr;
|
||||||
import dk.camelot64.kickc.model.*;
|
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.Label;
|
||||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
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.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 AsmFragmentInstanceSpecBuilder() {
|
||||||
private final Program program;
|
}
|
||||||
|
|
||||||
/** Binding of named values in the fragment to values (constants, variables, ...). */
|
|
||||||
private final Map<String, Value> 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a fragment instance spec factory for an indirect call.
|
* Create a fragment instance spec factory for an indirect call.
|
||||||
@ -46,17 +31,12 @@ public class AsmFragmentInstanceSpecBuilder {
|
|||||||
* @return the fragment instance spec factory
|
* @return the fragment instance spec factory
|
||||||
*/
|
*/
|
||||||
public static AsmFragmentInstanceSpec call(StatementCallExecute call, int indirectCallId, Program program) {
|
public static AsmFragmentInstanceSpec call(StatementCallExecute call, int indirectCallId, Program program) {
|
||||||
return new AsmFragmentInstanceSpecBuilder(call, indirectCallId, program).getAsmFragmentInstanceSpec();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
}
|
|
||||||
|
|
||||||
private AsmFragmentInstanceSpecBuilder(StatementCallExecute call, int indirectCallId, Program program) {
|
|
||||||
this.program = program;
|
|
||||||
this.bindings = new LinkedHashMap<>();
|
|
||||||
ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
|
ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
|
||||||
RValue procRVal = call.getProcedureRVal();
|
RValue procedureRVal = call.getProcedureRVal();
|
||||||
AsmFragmentSignature signature = new AsmFragmentSignature.Call(bind(procRVal));
|
AsmFragmentSignature signature = new AsmFragmentSignature.Call(bindings.bind(procedureRVal));
|
||||||
bind("la1", new LabelRef(codeScope.getFullName() + "::" + "icall" + indirectCallId));
|
bindings.bind("la1", new LabelRef(codeScope.getFullName() + "::" + "icall" + indirectCallId));
|
||||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature.getName(), bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,11 +47,10 @@ public class AsmFragmentInstanceSpecBuilder {
|
|||||||
* @return the fragment instance spec factory
|
* @return the fragment instance spec factory
|
||||||
*/
|
*/
|
||||||
public static AsmFragmentInstanceSpec interruptEntry(String interruptType, Program program) {
|
public static AsmFragmentInstanceSpec interruptEntry(String interruptType, Program program) {
|
||||||
Map<String, Value> bindings = new HashMap<>();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
String signature = "isr_" + interruptType + "_entry";
|
AsmFragmentSignature signature = new AsmFragmentSignature.IsrEntry(interruptType);
|
||||||
ScopeRef codeScope = program.getScope().getRef();
|
ScopeRef codeScope = program.getScope().getRef();
|
||||||
final AsmFragmentInstanceSpec fragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec).getAsmFragmentInstanceSpec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,147 +61,94 @@ public class AsmFragmentInstanceSpecBuilder {
|
|||||||
* @return the fragment instance spec factory
|
* @return the fragment instance spec factory
|
||||||
*/
|
*/
|
||||||
public static AsmFragmentInstanceSpec interruptExit(String interruptType, Program program) {
|
public static AsmFragmentInstanceSpec interruptExit(String interruptType, Program program) {
|
||||||
Map<String, Value> bindings = new HashMap<>();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
String signature = "isr_" + interruptType + "_exit";
|
AsmFragmentSignature signature = new AsmFragmentSignature.IsrExit(interruptType);
|
||||||
ScopeRef codeScope = program.getScope().getRef();
|
ScopeRef codeScope = program.getScope().getRef();
|
||||||
final AsmFragmentInstanceSpec fragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec).getAsmFragmentInstanceSpec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AsmFragmentInstanceSpecBuilder(Program program, Map<String, Value> bindings, AsmFragmentInstanceSpec asmFragmentInstanceSpec) {
|
|
||||||
this.program = program;
|
|
||||||
this.bindings = bindings;
|
|
||||||
this.asmFragmentInstanceSpec = asmFragmentInstanceSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static AsmFragmentInstanceSpec conditionalJump(StatementConditionalJump conditionalJump, ControlFlowBlock block, Program program) {
|
public static AsmFragmentInstanceSpec conditionalJump(StatementConditionalJump conditionalJump, ControlFlowBlock block, Program program) {
|
||||||
return new AsmFragmentInstanceSpecBuilder(conditionalJump, block, program).getAsmFragmentInstanceSpec();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
}
|
|
||||||
|
|
||||||
private AsmFragmentInstanceSpecBuilder(
|
|
||||||
StatementConditionalJump conditionalJump,
|
|
||||||
ControlFlowBlock block,
|
|
||||||
Program program) {
|
|
||||||
this.program = program;
|
|
||||||
this.bindings = new LinkedHashMap<>();
|
|
||||||
ScopeRef codeScope = program.getStatementInfos().getBlock(conditionalJump).getScope();
|
ScopeRef codeScope = program.getStatementInfos().getBlock(conditionalJump).getScope();
|
||||||
String signature = conditionalJumpSignature(conditionalJump, block, program.getGraph()).getName();
|
AsmFragmentSignature signature = conditionalJumpSignature(bindings, conditionalJump, block, program.getGraph());
|
||||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsmFragmentInstanceSpec exprSideEffect(StatementExprSideEffect exprSideEffect, Program program) {
|
public static AsmFragmentInstanceSpec exprSideEffect(StatementExprSideEffect exprSideEffect, Program program) {
|
||||||
return new AsmFragmentInstanceSpecBuilder(exprSideEffect, program).getAsmFragmentInstanceSpec();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
}
|
|
||||||
|
|
||||||
private AsmFragmentInstanceSpecBuilder(StatementExprSideEffect exprSideEffect, Program program) {
|
|
||||||
this.program = program;
|
|
||||||
this.bindings = new LinkedHashMap<>();
|
|
||||||
ScopeRef codeScope = program.getStatementInfos().getBlock(exprSideEffect).getScope();
|
ScopeRef codeScope = program.getStatementInfos().getBlock(exprSideEffect).getScope();
|
||||||
String signature = (new AsmFragmentSignature.ExprSideEffect(bind(exprSideEffect.getExpression()))).getName();
|
AsmFragmentSignature signature = new AsmFragmentSignature.ExprSideEffect(bindings.bind(exprSideEffect.getExpression()));
|
||||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
}
|
|
||||||
|
|
||||||
public static AsmFragmentInstanceSpec assignment(StatementAssignment assignment, Program program) {
|
|
||||||
return new AsmFragmentInstanceSpecBuilder(assignment, program).getAsmFragmentInstanceSpec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MAKELONG4() creates a long form 4 bytes
|
* MAKELONG4() creates a long form 4 bytes
|
||||||
*
|
*
|
||||||
* @param call The intrinsic call
|
* @param make4long The intrinsic call
|
||||||
* @param program The program
|
* @param program The program
|
||||||
* @return The ASM fragment instance
|
* @return The ASM fragment instance
|
||||||
*/
|
*/
|
||||||
public static AsmFragmentInstanceSpec makelong4(StatementCall call, Program program) {
|
public static AsmFragmentInstanceSpec makelong4(StatementCall make4long, Program program) {
|
||||||
return new AsmFragmentInstanceSpecBuilder(call, program).getAsmFragmentInstanceSpec();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
}
|
|
||||||
|
|
||||||
private AsmFragmentInstanceSpecBuilder(StatementCall make4long, Program program) {
|
|
||||||
this.program = program;
|
|
||||||
this.bindings = new LinkedHashMap<>();
|
|
||||||
if (make4long.getParameters().size() != 4)
|
if (make4long.getParameters().size() != 4)
|
||||||
throw new CompileError("MAKELONG4() needs 4 parameters.", make4long);
|
throw new CompileError("MAKELONG4() needs 4 parameters.", make4long);
|
||||||
final AsmFragmentSignature.Assignment signature = new AsmFragmentSignature.Assignment(
|
final AsmFragmentSignature.Assignment signature = new AsmFragmentSignature.Assignment(
|
||||||
bind(make4long.getlValue()),
|
bindings.bind(make4long.getlValue()),
|
||||||
new AsmFragmentSignatureExpr.Makelong4(
|
new AsmFragmentSignatureExpr.Makelong4(
|
||||||
bind(make4long.getParameter(3)),
|
bindings.bind(make4long.getParameter(3)),
|
||||||
bind(make4long.getParameter(2)),
|
bindings.bind(make4long.getParameter(2)),
|
||||||
bind(make4long.getParameter(1)),
|
bindings.bind(make4long.getParameter(1)),
|
||||||
bind(make4long.getParameter(0))
|
bindings.bind(make4long.getParameter(0))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
ScopeRef codeScope = program.getScope().getRef();
|
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) {
|
public static AsmFragmentInstanceSpec assignment(StatementAssignment assignment, Program program) {
|
||||||
this.program = program;
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
this.bindings = new LinkedHashMap<>();
|
|
||||||
ScopeRef codeScope = program.getStatementInfos().getBlock(assignment).getScope();
|
ScopeRef codeScope = program.getStatementInfos().getBlock(assignment).getScope();
|
||||||
String signature = assignmentSignature(
|
final AsmFragmentSignatureExpr lValueExpr = bindings.bind(assignment.getlValue());
|
||||||
assignment.getlValue(),
|
final AsmFragmentSignatureExpr rValueExpr = assignmentRightSideSignature(bindings, assignment.getrValue1(), assignment.getOperator(), assignment.getrValue2());
|
||||||
assignment.getrValue1(),
|
AsmFragmentSignature signature = new AsmFragmentSignature.Assignment(lValueExpr, rValueExpr);
|
||||||
assignment.getOperator(),
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
assignment.getrValue2());
|
|
||||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsmFragmentInstanceSpec assignment(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
|
public static AsmFragmentInstanceSpec assignment(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
|
||||||
return new AsmFragmentInstanceSpecBuilder(lValue, rValue, program, codeScopeRef).getAsmFragmentInstanceSpec();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
}
|
final AsmFragmentSignatureExpr lValueExpr = bindings.bind(lValue);
|
||||||
|
final AsmFragmentSignatureExpr rValueExpr = assignmentRightSideSignature(bindings, null, null, rValue);
|
||||||
private AsmFragmentInstanceSpecBuilder(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
|
AsmFragmentSignature signature = new AsmFragmentSignature.Assignment(lValueExpr, rValueExpr);
|
||||||
this.program = program;
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScopeRef);
|
||||||
this.bindings = new LinkedHashMap<>();
|
|
||||||
String signature = assignmentSignature(lValue, null, null, rValue);
|
|
||||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScopeRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsmFragmentInstanceSpec assignmentAlu(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
|
public static AsmFragmentInstanceSpec assignmentAlu(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
|
||||||
return new AsmFragmentInstanceSpecBuilder(assignment, assignmentAlu, program).getAsmFragmentInstanceSpec();
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
}
|
|
||||||
|
|
||||||
private AsmFragmentInstanceSpecBuilder(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
|
|
||||||
this.program = program;
|
|
||||||
this.bindings = new LinkedHashMap<>();
|
|
||||||
ScopeRef codeScope = program.getStatementInfos().getBlock(assignment).getScope();
|
ScopeRef codeScope = program.getStatementInfos().getBlock(assignment).getScope();
|
||||||
String signature = assignmentWithAluSignature(assignment, assignmentAlu).getName();
|
AsmFragmentSignature signature = assignmentWithAluSignature(bindings, assignment, assignmentAlu);
|
||||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Value> getBindings() {
|
private static AsmFragmentSignature assignmentWithAluSignature(AsmFragmentBindings bindingContext, StatementAssignment assignment, StatementAssignment assignmentAlu) {
|
||||||
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) {
|
|
||||||
if (!(assignment.getrValue2() instanceof VariableRef)) {
|
if (!(assignment.getrValue2() instanceof VariableRef)) {
|
||||||
throw new AsmFragmentInstance.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
|
throw new AsmFragmentInstance.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
|
||||||
}
|
}
|
||||||
VariableRef assignmentRValue2 = (VariableRef) assignment.getrValue2();
|
VariableRef assignmentRValue2 = (VariableRef) assignment.getrValue2();
|
||||||
Variable assignmentRValue2Var = program.getSymbolInfos().getVariable(assignmentRValue2);
|
Variable assignmentRValue2Var = bindingContext.program.getSymbolInfos().getVariable(assignmentRValue2);
|
||||||
Registers.Register rVal2Register = assignmentRValue2Var.getAllocation();
|
Registers.Register rVal2Register = assignmentRValue2Var.getAllocation();
|
||||||
|
|
||||||
if (!rVal2Register.getType().equals(Registers.RegisterType.REG_ALU)) {
|
if (!rVal2Register.getType().equals(Registers.RegisterType.REG_ALU)) {
|
||||||
throw new AsmFragmentInstance.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
|
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;
|
AsmFragmentSignatureExpr rVal1FragmentExpr = null;
|
||||||
if (assignment.getrValue1() != null) {
|
if (assignment.getrValue1() != null) {
|
||||||
rVal1FragmentExpr = bind(assignment.getrValue1());
|
rVal1FragmentExpr = bindingContext.bind(assignment.getrValue1());
|
||||||
}
|
}
|
||||||
|
|
||||||
final AsmFragmentSignatureExpr rVal2FragmentExpr = assignmentRightSideSignature(
|
final AsmFragmentSignatureExpr rVal2FragmentExpr = assignmentRightSideSignature(
|
||||||
|
bindingContext,
|
||||||
assignmentAlu.getrValue1(),
|
assignmentAlu.getrValue1(),
|
||||||
assignmentAlu.getOperator(),
|
assignmentAlu.getOperator(),
|
||||||
assignmentAlu.getrValue2());
|
assignmentAlu.getrValue2());
|
||||||
@ -240,62 +166,43 @@ public class AsmFragmentInstanceSpecBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String assignmentSignature(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) {
|
private static AsmFragmentSignatureExpr assignmentRightSideSignature(AsmFragmentBindings bindings, RValue rValue1, Operator operator, RValue rValue2) {
|
||||||
return (new AsmFragmentSignature.Assignment(
|
final SymbolType rValue1Type = rValue1 == null ? null : SymbolTypeInference.inferType(bindings.program.getScope(), rValue1);
|
||||||
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);
|
|
||||||
|
|
||||||
if (rValue1 == null && operator == null) {
|
if (rValue1 == null && operator == null) {
|
||||||
// Unmodified assignment
|
// Unmodified assignment
|
||||||
return bind(rValue2);
|
return bindings.bind(rValue2);
|
||||||
} else if (rValue1 == null) {
|
} else if (rValue1 == null) {
|
||||||
// Unary expression
|
// Unary expression
|
||||||
return new AsmFragmentSignatureExpr.Unary((OperatorUnary) operator, bind(rValue2));
|
return new AsmFragmentSignatureExpr.Unary((OperatorUnary) operator, bindings.bind(rValue2));
|
||||||
} else {
|
} else {
|
||||||
final AsmFragmentSignatureExpr rVal1SignatureExpr = bind(rValue1);
|
final AsmFragmentSignatureExpr rVal1SignatureExpr = bindings.bind(rValue1);
|
||||||
// Binary expression
|
// Binary expression
|
||||||
AsmFragmentSignatureExpr rVal2SignatureExpr;
|
AsmFragmentSignatureExpr rVal2SignatureExpr;
|
||||||
if (
|
final boolean isMinusOrPlus = Operators.MINUS.equals(operator) || Operators.PLUS.equals(operator);
|
||||||
rValue2 instanceof ConstantInteger &&
|
if (rValue2 instanceof ConstantInteger && ((ConstantInteger) rValue2).getValue() == 1 && isMinusOrPlus) {
|
||||||
((ConstantInteger) rValue2).getValue() == 1 &&
|
|
||||||
(Operators.MINUS.equals(operator) || Operators.PLUS.equals(operator))) {
|
|
||||||
rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(1L));
|
rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(1L));
|
||||||
} else if (
|
} else if (rValue2 instanceof ConstantInteger && ((ConstantInteger) rValue2).getValue() == 2 &&
|
||||||
rValue2 instanceof ConstantInteger &&
|
isMinusOrPlus && (SymbolType.BYTE.equals(rValue1Type) || SymbolType.SBYTE.equals(rValue1Type))
|
||||||
((ConstantInteger) rValue2).getValue() == 2 &&
|
|
||||||
(Operators.MINUS.equals(operator) || Operators.PLUS.equals(operator)) &&
|
|
||||||
(SymbolType.BYTE.equals(rValue1Type) || SymbolType.SBYTE.equals(rValue1Type))
|
|
||||||
) {
|
) {
|
||||||
rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(2L));
|
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 {
|
} 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);
|
return new AsmFragmentSignatureExpr.Binary((OperatorBinary) operator, rVal1SignatureExpr, rVal2SignatureExpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AsmFragmentSignature conditionalJumpSignature(
|
private static AsmFragmentSignature conditionalJumpSignature(
|
||||||
|
AsmFragmentBindings bindings,
|
||||||
StatementConditionalJump conditionalJump,
|
StatementConditionalJump conditionalJump,
|
||||||
ControlFlowBlock block,
|
ControlFlowBlock block,
|
||||||
ControlFlowGraph graph) {
|
ControlFlowGraph graph) {
|
||||||
@ -303,14 +210,14 @@ public class AsmFragmentInstanceSpecBuilder {
|
|||||||
if (conditionalJump.getrValue1() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue1()).getValue() == 0) {
|
if (conditionalJump.getrValue1() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue1()).getValue() == 0) {
|
||||||
rVal1SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(0L));
|
rVal1SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(0L));
|
||||||
} else if (conditionalJump.getrValue1() != null) {
|
} 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) {
|
if (conditionalJump.getrValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue2()).getValue() == 0) {
|
||||||
rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(0L));
|
rVal2SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(0L));
|
||||||
} else {
|
} else {
|
||||||
rVal2SignatureExpr = bind(conditionalJump.getrValue2());
|
rVal2SignatureExpr = bindings.bind(conditionalJump.getrValue2());
|
||||||
}
|
}
|
||||||
|
|
||||||
AsmFragmentSignatureExpr condition;
|
AsmFragmentSignatureExpr condition;
|
||||||
@ -334,343 +241,9 @@ public class AsmFragmentInstanceSpecBuilder {
|
|||||||
} else {
|
} else {
|
||||||
destinationLabel = destination.getLocalName();
|
destinationLabel = destination.getLocalName();
|
||||||
}
|
}
|
||||||
Symbol destSymbol = program.getScope().getSymbol(destination);
|
Symbol destSymbol = bindings.program.getScope().getSymbol(destination);
|
||||||
final AsmFragmentSignatureExpr labelExpr = bind(new Label(destinationLabel, destSymbol.getScope(), false));
|
final AsmFragmentSignatureExpr labelExpr = bindings.bind(new Label(destinationLabel, destSymbol.getScope(), false));
|
||||||
return new AsmFragmentSignature.ConditionalJump(condition, labelExpr);
|
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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -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<String, Value> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -85,4 +85,34 @@ public interface AsmFragmentSignature {
|
|||||||
return expr.getName();
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user