1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-07 20:31:32 +00:00

Added support for var_model in .TGT-file. Closes #448

This commit is contained in:
jespergravgaard 2020-05-29 21:57:19 +02:00
parent 8fbe49f272
commit 1786d85ea5
6 changed files with 66 additions and 69 deletions

View File

@ -44,9 +44,6 @@ public class Compiler {
*/ */
private boolean enableLoopHeadConstant = false; private boolean enableLoopHeadConstant = false;
/** Variable optimization/memory area configuration to use (from command line parameter). */
private VariableBuilderConfig variableBuilderConfig;
/** The initial calling convention to use when compiling (from command line parameter). */ /** The initial calling convention to use when compiling (from command line parameter). */
private Procedure.CallingConvention callingConvention; private Procedure.CallingConvention callingConvention;
@ -58,7 +55,7 @@ public class Compiler {
return program; return program;
} }
public void setDisableUplift(boolean disableUplift) { void setDisableUplift(boolean disableUplift) {
this.disableUplift = disableUplift; this.disableUplift = disableUplift;
} }
@ -66,14 +63,10 @@ public class Compiler {
program.setWarnFragmentMissing(warnFragmentMissing); program.setWarnFragmentMissing(warnFragmentMissing);
} }
public void setWarnArrayType(boolean warnArrayType) { void setWarnArrayType(boolean warnArrayType) {
program.setWarnArrayType(warnArrayType); program.setWarnArrayType(warnArrayType);
} }
public void setVariableBuilderConfig(VariableBuilderConfig variableBuilderConfig) {
this.variableBuilderConfig = variableBuilderConfig;
}
public void setCallingConvention(Procedure.CallingConvention callingConvention) { public void setCallingConvention(Procedure.CallingConvention callingConvention) {
this.callingConvention = callingConvention; this.callingConvention = callingConvention;
} }
@ -185,18 +178,11 @@ public class Compiler {
// Parse the files // Parse the files
KickCParser.FileContext cFileContext = cParser.getParser().file(); KickCParser.FileContext cFileContext = cParser.getParser().file();
if(variableBuilderConfig == null) {
VariableBuilderConfig config = new VariableBuilderConfig();
VariableBuilderConfig.defaultPreConfig(config, getLog());
VariableBuilderConfig.defaultPostConfig(config, getLog());
this.variableBuilderConfig = config;
}
if(callingConvention == null) { if(callingConvention == null) {
callingConvention = Procedure.CallingConvention.PHI_CALL; callingConvention = Procedure.CallingConvention.PHI_CALL;
} }
Pass0GenerateStatementSequence pass0GenerateStatementSequence = new Pass0GenerateStatementSequence(cParser, cFileContext, program, variableBuilderConfig, callingConvention); Pass0GenerateStatementSequence pass0GenerateStatementSequence = new Pass0GenerateStatementSequence(cParser, cFileContext, program, callingConvention);
pass0GenerateStatementSequence.generate(); pass0GenerateStatementSequence.generate();
StatementSequence sequence = program.getStatementSequence(); StatementSequence sequence = program.getStatementSequence();

View File

@ -329,8 +329,8 @@ public class KickC implements Callable<Integer> {
List<String> settings = Arrays.asList(varModel.split(",")); List<String> settings = Arrays.asList(varModel.split(","));
settings = settings.stream().map(String::trim).collect(Collectors.toList()); settings = settings.stream().map(String::trim).collect(Collectors.toList());
try { try {
VariableBuilderConfig config = VariableBuilderConfig.fromSettings(settings, StatementSource.NONE, compiler.getLog()); VariableBuilderConfig config = VariableBuilderConfig.fromSettings(settings, StatementSource.NONE);
compiler.setVariableBuilderConfig(config); program.getTargetPlatform().setVariableBuilderConfig(config);
} catch(CompileError e) { } catch(CompileError e) {
System.err.println(e.getMessage()); System.err.println(e.getMessage());
return COMPILE_ERROR; return COMPILE_ERROR;

View File

@ -39,8 +39,15 @@ public class TargetPlatform {
/** Reserved zeropage addresses. */ /** Reserved zeropage addresses. */
private List<Integer> reservedZps = new ArrayList<>(); private List<Integer> reservedZps = new ArrayList<>();
/** Configuration for the variable builder. */
private VariableBuilderConfig variableBuilderConfig;
public TargetPlatform(String name) { public TargetPlatform(String name) {
this.name = name; this.name = name;
VariableBuilderConfig config = new VariableBuilderConfig();
VariableBuilderConfig.defaultPreConfig(config);
VariableBuilderConfig.defaultPostConfig(config);
this.variableBuilderConfig = config;
} }
public String getName() { public String getName() {
@ -111,4 +118,12 @@ public class TargetPlatform {
public List<Integer> getReservedZps() { public List<Integer> getReservedZps() {
return reservedZps; return reservedZps;
} }
public VariableBuilderConfig getVariableBuilderConfig() {
return variableBuilderConfig;
}
public void setVariableBuilderConfig(VariableBuilderConfig variableBuilderConfig) {
this.variableBuilderConfig = variableBuilderConfig;
}
} }

View File

@ -47,7 +47,7 @@ public class VariableBuilderConfig {
* @param program The program log (used for error messages) * @param program The program log (used for error messages)
* @return A variable builder configuration * @return A variable builder configuration
*/ */
public static VariableBuilderConfig fromSettings(List<String> settings, StatementSource statementSource, CompileLog log) { public static VariableBuilderConfig fromSettings(List<String> settings, StatementSource statementSource) {
// Detect if the first setting is "full" // Detect if the first setting is "full"
boolean full = false; boolean full = false;
if(settings.size() > 0 && settings.get(0).equals(SETTING_FULL)) { if(settings.size() > 0 && settings.get(0).equals(SETTING_FULL)) {
@ -56,13 +56,13 @@ public class VariableBuilderConfig {
} }
VariableBuilderConfig config = new VariableBuilderConfig(); VariableBuilderConfig config = new VariableBuilderConfig();
if(!full) if(!full)
defaultPreConfig(config, log); defaultPreConfig(config);
// Apply all settings // Apply all settings
for(String setting : settings) { for(String setting : settings) {
config.addSetting(setting, log, statementSource); config.addSetting(setting, statementSource);
} }
if(!full) if(!full)
defaultPostConfig(config, log); defaultPostConfig(config);
return config; return config;
} }
@ -75,8 +75,8 @@ public class VariableBuilderConfig {
* @param config The variable builder configuration * @param config The variable builder configuration
* @param log The compile log * @param log The compile log
*/ */
public static void defaultPreConfig(VariableBuilderConfig config, CompileLog log) { public static void defaultPreConfig(VariableBuilderConfig config) {
config.addSetting("ssa_zp", log, StatementSource.NONE); config.addSetting("ssa_zp", StatementSource.NONE);
} }
/** /**
@ -85,15 +85,15 @@ public class VariableBuilderConfig {
* @param config The variable builder configuration * @param config The variable builder configuration
* @param log The compile log * @param log The compile log
*/ */
public static void defaultPostConfig(VariableBuilderConfig config, CompileLog log) { public static void defaultPostConfig(VariableBuilderConfig config) {
// Arrays are always load/store variables in main memory // Arrays are always load/store variables in main memory
config.addSetting("array_ma_mem", log, StatementSource.NONE); config.addSetting("array_ma_mem", StatementSource.NONE);
// Global struct values are always load/store variables in main memory // Global struct values are always load/store variables in main memory
config.addSetting("global_struct_ma_mem", log, StatementSource.NONE); config.addSetting("global_struct_ma_mem", StatementSource.NONE);
// Parameters are always passed using single-static-assignment // Parameters are always passed using single-static-assignment
config.addSetting("parameter_ssa", log, StatementSource.NONE); config.addSetting("parameter_ssa", StatementSource.NONE);
// Pointers are always on zeropage // Pointers are always on zeropage
config.addSetting("pointer_zp", log, StatementSource.NONE); config.addSetting("pointer_zp", StatementSource.NONE);
} }
/** The different scopes. */ /** The different scopes. */
@ -170,7 +170,7 @@ public class VariableBuilderConfig {
this.settings = new HashMap<>(); this.settings = new HashMap<>();
} }
public void addSetting(String pragmaParam, CompileLog log, StatementSource statementSource) { public void addSetting(String pragmaParam, StatementSource statementSource) {
List<String> paramElements = new ArrayList<>(Arrays.asList(pragmaParam.split("_"))); List<String> paramElements = new ArrayList<>(Arrays.asList(pragmaParam.split("_")));
List<Scope> scopes = getScopes(paramElements); List<Scope> scopes = getScopes(paramElements);
List<Type> types = getTypes(paramElements); List<Type> types = getTypes(paramElements);

View File

@ -5,6 +5,8 @@ import dk.camelot64.kickc.SourceLoader;
import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.TargetCpu; import dk.camelot64.kickc.model.TargetCpu;
import dk.camelot64.kickc.model.TargetPlatform; import dk.camelot64.kickc.model.TargetPlatform;
import dk.camelot64.kickc.model.VariableBuilderConfig;
import dk.camelot64.kickc.model.statements.StatementSource;
import javax.json.*; import javax.json.*;
import javax.json.stream.JsonParsingException; import javax.json.stream.JsonParsingException;
@ -14,9 +16,9 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.stream.Collectors;
/** /**
* Parser for target platform files xxx.tgt. * Parser for target platform files xxx.tgt.
@ -87,16 +89,12 @@ public class CTargetPlatformParser {
} }
} }
{ {
final JsonObject defines = platformJson.getJsonObject("defines"); final String varModel = platformJson.getString("var_model", null);
if(defines != null) { if(varModel != null) {
final Set<String> macroNames = defines.keySet(); List<String> settings = Arrays.asList(varModel.split(","));
final LinkedHashMap<String, String> macros = new LinkedHashMap<>(); settings = settings.stream().map(String::trim).collect(Collectors.toList());
for(String macroName : macroNames) { VariableBuilderConfig config = VariableBuilderConfig.fromSettings(settings, StatementSource.NONE);
final JsonValue jsonValue = defines.get(macroName); targetPlatform.setVariableBuilderConfig(config);
final String macroBody = jsonValue.toString();
macros.put(macroName, macroBody);
}
targetPlatform.setDefines(macros);
} }
} }
return targetPlatform; return targetPlatform;

View File

@ -46,17 +46,14 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
private Stack<Scope> scopeStack; private Stack<Scope> scopeStack;
/** The memory area used by default for variables. */ /** The memory area used by default for variables. */
private Variable.MemoryArea defaultMemoryArea; private Variable.MemoryArea defaultMemoryArea;
/** Configuration for the variable builder. */
private VariableBuilderConfig variableBuilderConfig;
public Pass0GenerateStatementSequence(CParser cParser, KickCParser.FileContext fileCtx, Program program, VariableBuilderConfig variableBuilderConfig, Procedure.CallingConvention initialCallingConvention) { public Pass0GenerateStatementSequence(CParser cParser, KickCParser.FileContext fileCtx, Program program, Procedure.CallingConvention initialCallingConvention) {
this.cParser = cParser; this.cParser = cParser;
this.fileCtx = fileCtx; this.fileCtx = fileCtx;
this.program = program; this.program = program;
this.sequence = program.getStatementSequence(); this.sequence = program.getStatementSequence();
this.scopeStack = new Stack<>(); this.scopeStack = new Stack<>();
this.defaultMemoryArea = Variable.MemoryArea.ZEROPAGE_MEMORY; this.defaultMemoryArea = Variable.MemoryArea.ZEROPAGE_MEMORY;
this.variableBuilderConfig = variableBuilderConfig;
this.currentCallingConvention = initialCallingConvention; this.currentCallingConvention = initialCallingConvention;
scopeStack.push(program.getScope()); scopeStack.push(program.getScope());
} }
@ -122,7 +119,8 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
public Object visitGlobalDirectiveVarModel(KickCParser.GlobalDirectiveVarModelContext ctx) { public Object visitGlobalDirectiveVarModel(KickCParser.GlobalDirectiveVarModelContext ctx) {
List<TerminalNode> settingNodes = new ArrayList<>(ctx.NAME()); List<TerminalNode> settingNodes = new ArrayList<>(ctx.NAME());
List<String> settings = settingNodes.stream().map(ParseTree::getText).collect(Collectors.toList()); List<String> settings = settingNodes.stream().map(ParseTree::getText).collect(Collectors.toList());
this.variableBuilderConfig = VariableBuilderConfig.fromSettings(settings, new StatementSource(ctx), program.getLog()); final VariableBuilderConfig variableBuilderConfig = VariableBuilderConfig.fromSettings(settings, new StatementSource(ctx));
program.getTargetPlatform().setVariableBuilderConfig(variableBuilderConfig);
return null; return null;
} }
@ -372,7 +370,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
this.visit(declPointerContext); this.visit(declPointerContext);
} }
String varName = ctx.NAME().getText(); String varName = ctx.NAME().getText();
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), true, varDecl.getEffectiveType(), null, varDecl.getEffectiveDirectives(), currentDataSegment, variableBuilderConfig); VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), true, varDecl.getEffectiveType(), null, varDecl.getEffectiveDirectives(), currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
Variable param = varBuilder.build(); Variable param = varBuilder.build();
varDecl.exitType(); varDecl.exitType();
return param; return param;
@ -645,7 +643,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
/** The declared type (variable level) */ /** The declared type (variable level) */
private VariableDeclType varDeclType; private VariableDeclType varDeclType;
public VariableDeclaration() { VariableDeclaration() {
this.declType = new VariableDeclType(); this.declType = new VariableDeclType();
} }
@ -677,7 +675,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
/** If the type is SymbolTypePointer this holds the declaration type of the elements. */ /** If the type is SymbolTypePointer this holds the declaration type of the elements. */
VariableDeclType elementDeclType; VariableDeclType elementDeclType;
public VariableDeclType() { VariableDeclType() {
this.typeDirectives = new ArrayList<>(); this.typeDirectives = new ArrayList<>();
} }
@ -693,23 +691,23 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return arraySpec; return arraySpec;
} }
public List<Directive> getTypeDirectives() { List<Directive> getTypeDirectives() {
return typeDirectives; return typeDirectives;
} }
public void setTypeDirectives(List<Directive> directives) { void setTypeDirectives(List<Directive> directives) {
this.typeDirectives = directives; this.typeDirectives = directives;
} }
public void setElementDeclType(VariableDeclType elementDeclType) { void setElementDeclType(VariableDeclType elementDeclType) {
this.elementDeclType = elementDeclType; this.elementDeclType = elementDeclType;
} }
public void setArraySpec(ArraySpec arraySpec) { void setArraySpec(ArraySpec arraySpec) {
this.arraySpec = arraySpec; this.arraySpec = arraySpec;
} }
public VariableDeclType getElementDeclType() { VariableDeclType getElementDeclType() {
return elementDeclType; return elementDeclType;
} }
} }
@ -779,7 +777,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return dirs; return dirs;
} }
public List<Comment> getDeclComments() { List<Comment> getDeclComments() {
return declComments; return declComments;
} }
@ -795,7 +793,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
this.declType.setType(type); this.declType.setType(type);
} }
public void setVarDeclType(VariableDeclType varDeclType) { void setVarDeclType(VariableDeclType varDeclType) {
this.varDeclType = varDeclType; this.varDeclType = varDeclType;
} }
@ -803,7 +801,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return varDeclType; return varDeclType;
} }
public void setDeclComments(List<Comment> declComments) { void setDeclComments(List<Comment> declComments) {
this.declComments = declComments; this.declComments = declComments;
} }
@ -822,7 +820,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
/** /**
* Push the current type declaration handler onto the stack and initialize a new empty current type declaration handler. * Push the current type declaration handler onto the stack and initialize a new empty current type declaration handler.
*/ */
void varDeclPush() { private void varDeclPush() {
varDeclStack.push(varDecl); varDeclStack.push(varDecl);
varDecl = new VariableDeclaration(); varDecl = new VariableDeclaration();
} }
@ -830,7 +828,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
/** /**
* Discard the current type declaration handler and pop the last one fron the stack. * Discard the current type declaration handler and pop the last one fron the stack.
*/ */
void varDeclPop() { private void varDeclPop() {
this.varDecl = varDeclStack.pop(); this.varDecl = varDeclStack.pop();
} }
@ -924,7 +922,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
final List<Directive> effectiveDirectives = varDecl.getEffectiveDirectives(); final List<Directive> effectiveDirectives = varDecl.getEffectiveDirectives();
final List<Comment> declComments = varDecl.getDeclComments(); final List<Comment> declComments = varDecl.getDeclComments();
varDecl.exitVar(); varDecl.exitVar();
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, effectiveType, effectiveArraySpec, effectiveDirectives, currentDataSegment, variableBuilderConfig); VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, effectiveType, effectiveArraySpec, effectiveDirectives, currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
Variable variable = varBuilder.build(); Variable variable = varBuilder.build();
if(isStructMember && (initializer != null)) if(isStructMember && (initializer != null))
throw new CompileError("Initializer not supported inside structs " + effectiveType.getTypeName(), statementSource); throw new CompileError("Initializer not supported inside structs " + effectiveType.getTypeName(), statementSource);
@ -1007,7 +1005,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
sequence.getStatements().remove(sequence.getStatements().size() - 1); sequence.getStatements().remove(sequence.getStatements().size() - 1);
// Add a constant variable // Add a constant variable
Scope scope = getCurrentScope(); Scope scope = getCurrentScope();
VariableBuilder varBuilder = new VariableBuilder(varName, scope, false, varDecl.getEffectiveType(), varDecl.getEffectiveArraySpec(), varDecl.getEffectiveDirectives(), currentDataSegment, variableBuilderConfig); VariableBuilder varBuilder = new VariableBuilder(varName, scope, false, varDecl.getEffectiveType(), varDecl.getEffectiveArraySpec(), varDecl.getEffectiveDirectives(), currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
Variable variable = varBuilder.build(); Variable variable = varBuilder.build();
// Set constant value // Set constant value
variable.setInitValue(getConstInitValue(constantArrayKickAsm, null, statementSource)); variable.setInitValue(getConstInitValue(constantArrayKickAsm, null, statementSource));
@ -1530,7 +1528,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
String varName = ctx.NAME().getText(); String varName = ctx.NAME().getText();
Variable lValue; Variable lValue;
if(varType != null) { if(varType != null) {
VariableBuilder varBuilder = new VariableBuilder(varName, blockScope, false, varType, null, varDecl.getEffectiveDirectives(), currentDataSegment, variableBuilderConfig); VariableBuilder varBuilder = new VariableBuilder(varName, blockScope, false, varType, null, varDecl.getEffectiveDirectives(), currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
lValue = varBuilder.build(); lValue = varBuilder.build();
} else { } else {
lValue = getCurrentScope().findVariable(varName); lValue = getCurrentScope().findVariable(varName);
@ -1984,7 +1982,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
this.visit(declArrayContext); this.visit(declArrayContext);
} }
String typedefName = ctx.NAME().getText(); String typedefName = ctx.NAME().getText();
VariableBuilder varBuilder = new VariableBuilder(typedefName, getCurrentScope(), false, varDecl.getEffectiveType(), varDecl.getEffectiveArraySpec(), varDecl.getEffectiveDirectives(), currentDataSegment, variableBuilderConfig); VariableBuilder varBuilder = new VariableBuilder(typedefName, getCurrentScope(), false, varDecl.getEffectiveType(), varDecl.getEffectiveArraySpec(), varDecl.getEffectiveDirectives(), currentDataSegment, program.getTargetPlatform().getVariableBuilderConfig());
final Variable typeDefVar = varBuilder.build(); final Variable typeDefVar = varBuilder.build();
scopeStack.pop(); scopeStack.pop();
varDecl.exitType(); varDecl.exitType();