From 1d534dcc3dc1c1a8c2bd778c0ade5ad368bf28c6 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Fri, 15 May 2020 08:19:26 +0200 Subject: [PATCH] Implemented target platform defines by putting the handling of #pragma target() into the preprocessor/parser. --- src/main/java/dk/camelot64/kickc/KickC.java | 16 +- .../camelot64/kickc/model/TargetPlatform.java | 69 ------ .../dk/camelot64/kickc/parser/CParser.java | 35 ++- .../kickc/parser/CTargetPlatformParser.java | 64 +++++ .../Pass0GenerateStatementSequence.java | 16 +- .../kickc/preprocessor/CPreprocessor.java | 95 ++------ src/main/kc/include/c64.h | 3 + .../dk/camelot64/kickc/test/TestPrograms.java | 22 +- src/test/kc/platform-default-define.c | 11 + src/test/kc/platform-plus4-define.c | 12 + src/test/kc/plus4-define.c | 12 - src/test/ref/platform-default-define.asm | 12 + src/test/ref/platform-default-define.cfg | 17 ++ src/test/ref/platform-default-define.log | 216 +++++++++++++++++ src/test/ref/platform-default-define.sym | 7 + src/test/ref/platform-plus4-define.asm | 13 ++ src/test/ref/platform-plus4-define.cfg | 17 ++ src/test/ref/platform-plus4-define.log | 219 ++++++++++++++++++ src/test/ref/platform-plus4-define.sym | 7 + 19 files changed, 672 insertions(+), 191 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/parser/CTargetPlatformParser.java create mode 100644 src/test/kc/platform-default-define.c create mode 100644 src/test/kc/platform-plus4-define.c delete mode 100644 src/test/kc/plus4-define.c create mode 100644 src/test/ref/platform-default-define.asm create mode 100644 src/test/ref/platform-default-define.cfg create mode 100644 src/test/ref/platform-default-define.log create mode 100644 src/test/ref/platform-default-define.sym create mode 100644 src/test/ref/platform-plus4-define.asm create mode 100644 src/test/ref/platform-plus4-define.cfg create mode 100644 src/test/ref/platform-plus4-define.log create mode 100644 src/test/ref/platform-plus4-define.sym diff --git a/src/main/java/dk/camelot64/kickc/KickC.java b/src/main/java/dk/camelot64/kickc/KickC.java index 814a4818b..e1c0f7fd5 100644 --- a/src/main/java/dk/camelot64/kickc/KickC.java +++ b/src/main/java/dk/camelot64/kickc/KickC.java @@ -6,6 +6,7 @@ import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages; import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.statements.StatementSource; import dk.camelot64.kickc.model.symbols.Procedure; +import dk.camelot64.kickc.parser.CTargetPlatformParser; import kickass.KickAssembler; import kickass.nonasm.c64.CharToPetsciiConverter; import picocli.CommandLine; @@ -156,7 +157,7 @@ public class KickC implements Callable { private boolean interleaveIclFile = false; @CommandLine.Option(names = {"-p", "-t", "-target", "-platform"}, description = "The target platform. Default is C64 with BASIC upstart. See #pragma target") - private String targetPlatform = null; + private String targetPlatform = TargetPlatform.DEFAULT_NAME; @CommandLine.Option(names = {"-cpu"}, description = "The target CPU. Default is 6502 with illegal opcodes. See #pragma cpu") private String cpu = null; @@ -228,18 +229,15 @@ public class KickC implements Callable { // Set up Target Platform try { - if(targetPlatform != null) { - TargetPlatform.setTargetPlatform(targetPlatform, currentPath, program, null); - } else { - TargetPlatform.setTargetPlatform(TargetPlatform.DEFAULT_NAME, currentPath, program, null); - } + final File platformFile = SourceLoader.loadFile(targetPlatform + "." + CTargetPlatformParser.FILE_EXTENSION, currentPath, program.getTargetPlatformPaths()); + final TargetPlatform targetPlatform = CTargetPlatformParser.parseTargetPlatformFile(this.targetPlatform, platformFile, currentPath, program.getTargetPlatformPaths()); + program.setTargetPlatform(targetPlatform); } catch(CompileError e) { // Print the error and exit with compile error System.err.println(e.getMessage()); return COMPILE_ERROR; } - // Update link script if(linkScript != null) { program.getTargetPlatform().setLinkScriptFile(SourceLoader.loadFile(linkScript, currentPath, program.getTargetPlatformPaths())); @@ -350,9 +348,9 @@ public class KickC implements Callable { cFiles.stream().forEach(path -> CFileNames.append(path.toString()).append(" ")); Map effectiveDefines = new LinkedHashMap<>(); - if(defines!=null) + if(defines != null) effectiveDefines.putAll(defines); - if(program.getTargetPlatform().getDefines()!=null) + if(program.getTargetPlatform().getDefines() != null) effectiveDefines.putAll(program.getTargetPlatform().getDefines()); if(preprocess) { diff --git a/src/main/java/dk/camelot64/kickc/model/TargetPlatform.java b/src/main/java/dk/camelot64/kickc/model/TargetPlatform.java index 68386c526..1e679159c 100644 --- a/src/main/java/dk/camelot64/kickc/model/TargetPlatform.java +++ b/src/main/java/dk/camelot64/kickc/model/TargetPlatform.java @@ -1,22 +1,7 @@ package dk.camelot64.kickc.model; -import dk.camelot64.kickc.SourceLoader; -import dk.camelot64.kickc.model.statements.StatementSource; - -import javax.json.Json; -import javax.json.JsonObject; -import javax.json.JsonReader; -import javax.json.JsonValue; -import javax.json.stream.JsonParsingException; -import java.io.BufferedInputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.Set; /** * The target platform the compiler is creating a program for. @@ -29,9 +14,6 @@ public class TargetPlatform { /** The name of the default target platform. */ public static String DEFAULT_NAME = "c64basic"; - /** The file extension used for target platform files. */ - public static final String FILE_EXTENSION = "tgt"; - /** The platform name. */ private String name; @@ -91,56 +73,5 @@ public class TargetPlatform { this.defines = defines; } - /** - * Set the target platform from a platform name - * - * @param platformName The platform name - * @param currentFolder The current folder (added to the search path) - * @param program The program. - * @param statementSource The source file & line used for errors - */ - public static void setTargetPlatform(String platformName, Path currentFolder, Program program, StatementSource statementSource) { - final File platformFile = SourceLoader.loadFile(platformName + "." + FILE_EXTENSION, currentFolder, program.getTargetPlatformPaths()); - if(platformFile != null) { - // Set the target platform - try { - final JsonReader jsonReader = Json.createReader(new BufferedInputStream(new FileInputStream(platformFile))); - final JsonObject platformJson = jsonReader.readObject(); - TargetPlatform targetPlatform = new TargetPlatform(platformName); - final String cpuName = platformJson.getString("cpu", null); - if(cpuName != null) - targetPlatform.setCpu(TargetCpu.getTargetCpu(cpuName, false)); - final String linkScriptName = platformJson.getString("link", null); - if(linkScriptName != null) - targetPlatform.setLinkScriptFile(SourceLoader.loadFile(linkScriptName, currentFolder, program.getTargetPlatformPaths())); - final String emulatorCommand = platformJson.getString("emulator", null); - if(emulatorCommand != null) - targetPlatform.setEmulatorCommand(emulatorCommand); - final JsonObject defines = platformJson.getJsonObject("defines"); - if(defines!=null) { - final Set macroNames = defines.keySet(); - final LinkedHashMap macros = new LinkedHashMap<>(); - for(String macroName : macroNames) { - final JsonValue jsonValue = defines.get(macroName); - final String macroBody = jsonValue.toString(); - macros.put(macroName, macroBody); - } - targetPlatform.setDefines(macros); - } - program.setTargetPlatform(targetPlatform); - } catch(CompileError | IOException | JsonParsingException e) { - throw new CompileError("Error parsing target platform file " + platformFile.getAbsolutePath() + "\n"+e.getMessage(), statementSource); - } - } else { - StringBuilder supported = new StringBuilder(); - final List platformFiles = SourceLoader.listFiles(currentFolder, program.getTargetPlatformPaths(), FILE_EXTENSION); - for(File file : platformFiles) { - String name = file.getName(); - name = name.substring(0, name.length()- FILE_EXTENSION.length()-1); - supported.append(name).append(" "); - } - throw new CompileError("Unknown target platform '"+platformName+"'. Supported: " + supported.toString(), statementSource); - } - } } diff --git a/src/main/java/dk/camelot64/kickc/parser/CParser.java b/src/main/java/dk/camelot64/kickc/parser/CParser.java index c118b9600..d8db4f989 100644 --- a/src/main/java/dk/camelot64/kickc/parser/CParser.java +++ b/src/main/java/dk/camelot64/kickc/parser/CParser.java @@ -4,6 +4,7 @@ import dk.camelot64.kickc.Compiler; import dk.camelot64.kickc.SourceLoader; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.TargetPlatform; import dk.camelot64.kickc.preprocessor.CPreprocessor; import org.antlr.v4.runtime.*; @@ -65,7 +66,7 @@ public class CParser { this.program = program; this.cFiles = new LinkedHashMap<>(); this.cTokenSource = new CTokenSource(); - this.preprocessor = new CPreprocessor(cTokenSource, new HashMap<>()); + this.preprocessor = new CPreprocessor(this, cTokenSource, new HashMap<>()); this.preprocessedTokenStream = new CommonTokenStream(preprocessor); this.parser = new KickCParser(preprocessedTokenStream, this); this.typedefs = new ArrayList<>(); @@ -103,6 +104,7 @@ public class CParser { /** * Define a new macro + * * @param macroName The macro name * @param macroBody The macro body */ @@ -115,6 +117,7 @@ public class CParser { /** * Undef a macro + * * @param macroName The macro name */ public void undef(String macroName) { @@ -158,7 +161,7 @@ public class CParser { * * @return The path of the folder containing the source file currently being tokenized */ - private Path getCurrentSourceFolderPath() { + public Path getCurrentSourceFolderPath() { TokenSource currentSource = cTokenSource.getCurrentSource(); String sourceName = currentSource.getSourceName(); CFile cFile = cFiles.get(sourceName); @@ -224,6 +227,34 @@ public class CParser { } } + public void loadTargetPlatform(String platformName, Path currentPath) { + final File platformFile = SourceLoader.loadFile(platformName + "." + CTargetPlatformParser.FILE_EXTENSION, currentPath, program.getTargetPlatformPaths()); + if(platformFile != null) { + final TargetPlatform targetPlatform = CTargetPlatformParser.parseTargetPlatformFile(platformName, platformFile, currentPath, program.getTargetPlatformPaths()); + // Remove macros from existing platform! + if(program.getTargetPlatform() != null && program.getTargetPlatform().getDefines() != null) + for(String macroName : program.getTargetPlatform().getDefines().keySet()) + preprocessor.undef(macroName); + // Set the new program platform + program.setTargetPlatform(targetPlatform); + // Define macros from new platform! + if(program.getTargetPlatform().getDefines() != null) + for(String macroName : program.getTargetPlatform().getDefines().keySet()) + define(macroName, program.getTargetPlatform().getDefines().get(macroName)); + // Re-initialize ASM fragment synthesizer + program.initAsmFragmentSynthesizer(); + } else { + StringBuilder supported = new StringBuilder(); + final List platformFiles = SourceLoader.listFiles(currentPath, program.getTargetPlatformPaths(), CTargetPlatformParser.FILE_EXTENSION); + for(File file : platformFiles) { + String name = file.getName(); + name = name.substring(0, name.length() - CTargetPlatformParser.FILE_EXTENSION.length() - 1); + supported.append(name).append(" "); + } + throw new CompileError("Unknown target platform '" + platformName + "'. Supported: " + supported.toString()); + } + } + /** * Make a lexer for a char stream * diff --git a/src/main/java/dk/camelot64/kickc/parser/CTargetPlatformParser.java b/src/main/java/dk/camelot64/kickc/parser/CTargetPlatformParser.java new file mode 100644 index 000000000..9a5cc337c --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/parser/CTargetPlatformParser.java @@ -0,0 +1,64 @@ +package dk.camelot64.kickc.parser; + +import dk.camelot64.kickc.SourceLoader; +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.TargetCpu; +import dk.camelot64.kickc.model.TargetPlatform; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.JsonValue; +import javax.json.stream.JsonParsingException; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; + +/** + * Parser for target platform files xxx.tgt. + * The file format is JSON. + */ +public class CTargetPlatformParser { + + /** The file extension used for target platform files. */ + public static final String FILE_EXTENSION = "tgt"; + + + public static TargetPlatform parseTargetPlatformFile(String platformName, File platformFile, Path currentFolder, List platformSearchPaths) { + try { + final JsonReader jsonReader = Json.createReader(new BufferedInputStream(new FileInputStream(platformFile))); + final JsonObject platformJson = jsonReader.readObject(); + TargetPlatform targetPlatform = new TargetPlatform(platformName); + final String cpuName = platformJson.getString("cpu", null); + if(cpuName != null) + targetPlatform.setCpu(TargetCpu.getTargetCpu(cpuName, false)); + final String linkScriptName = platformJson.getString("link", null); + if(linkScriptName != null) + targetPlatform.setLinkScriptFile(SourceLoader.loadFile(linkScriptName, currentFolder, platformSearchPaths)); + final String emulatorCommand = platformJson.getString("emulator", null); + if(emulatorCommand != null) + targetPlatform.setEmulatorCommand(emulatorCommand); + final JsonObject defines = platformJson.getJsonObject("defines"); + if(defines != null) { + final Set macroNames = defines.keySet(); + final LinkedHashMap macros = new LinkedHashMap<>(); + for(String macroName : macroNames) { + final JsonValue jsonValue = defines.get(macroName); + final String macroBody = jsonValue.toString(); + macros.put(macroName, macroBody); + } + targetPlatform.setDefines(macros); + } + return targetPlatform; + } catch(CompileError | IOException | JsonParsingException e) { + throw new CompileError("Error parsing target platform file " + platformFile.getAbsolutePath() + "\n" + e.getMessage()); + } + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 556f616ca..fed9bbe43 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -179,21 +179,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor defines) { + public CPreprocessor(CParser cParser, TokenSource input, Map defines) { + this.cParser = cParser; if(input instanceof CTokenSource) { // If possible use the input directly instead of wrapping it this.input = (CTokenSource) input; @@ -135,12 +139,15 @@ public class CPreprocessor implements TokenSource { return true; } else if(inputToken.getType() == KickCLexer.NAME) { return expand(inputToken, cTokenSource); - //} else if(inputToken.getType() == KickCLexer.PRAGMA) { - // return pragma(inputToken, cTokenSource); + } else if(inputToken.getType() == KickCLexer.PRAGMA) { + return pragma(inputToken, cTokenSource); } return false; } + /** #pragmas to be handled by the parser (skipped in the preprocessor). */ + private List parserPragmas = new ArrayList<>(); + /** * Handle any #pragma that must be handled by the preprocessor * @@ -149,13 +156,11 @@ public class CPreprocessor implements TokenSource { * @return true if the input token was preprocessed (and should not be added to the output). False if the token was not a preprocessor token */ private boolean pragma(Token inputToken, CTokenSource cTokenSource) { - if(inputToken instanceof PragmaToken) + if(parserPragmas.contains(inputToken)) // Already examined by the preprocessor - and determined to be for the parser return false; final List ws = skipWhitespace(cTokenSource); final Token pragmaType = cTokenSource.nextToken(); - - /* if(KickCLexer.TARGET == pragmaType.getType()) { skipWhitespace(cTokenSource); nextToken(cTokenSource, KickCLexer.PAR_BEGIN); @@ -163,15 +168,14 @@ public class CPreprocessor implements TokenSource { final String targetName = nextToken(cTokenSource, KickCLexer.NAME).getText(); skipWhitespace(cTokenSource); nextToken(cTokenSource, KickCLexer.PAR_END); - //TargetPlatform.setTargetPlatform(targetName, null, ); - throw new InternalError("TODO: Implement #pragma target"); - // return true; + cParser.loadTargetPlatform(targetName, cParser.getCurrentSourceFolderPath()); + return true; } - */ // Pass on the #pragma to the parser + parserPragmas.add(inputToken); final ArrayList pragmaTokens = new ArrayList<>(); - pragmaTokens.add(new PragmaToken(inputToken)); + pragmaTokens.add(inputToken); pragmaTokens.addAll(ws); pragmaTokens.add(pragmaType); cTokenSource.addSourceFirst(new ListTokenSource(pragmaTokens)); @@ -280,7 +284,7 @@ public class CPreprocessor implements TokenSource { List> expandedParamValues = new ArrayList<>(); for(List paramTokens : paramValues) { List expandedParamValue = new ArrayList<>(); - CPreprocessor subPreprocessor = new CPreprocessor(new ListTokenSource(paramTokens), new HashMap<>(defines)); + CPreprocessor subPreprocessor = new CPreprocessor(cParser, new ListTokenSource(paramTokens), new HashMap<>(defines)); while(true) { final Token expandedToken = subPreprocessor.nextToken(); if(expandedToken.getType() == Token.EOF) @@ -409,7 +413,7 @@ public class CPreprocessor implements TokenSource { // Evaluate any uses of the defined operator (to prevent expansion of the named macro) evaluateDefinedOperator(conditionTokens); // Expand the condition body before evaluating it - CPreprocessor subPreprocessor = new CPreprocessor(new ListTokenSource(conditionTokens), new HashMap<>(defines)); + CPreprocessor subPreprocessor = new CPreprocessor(cParser, new ListTokenSource(conditionTokens), new HashMap<>(defines)); // Parse the expression KickCParser.ExprContext conditionExpr = ExprParser.parseExpression(subPreprocessor); // Evaluate the expression @@ -730,69 +734,4 @@ public class CPreprocessor implements TokenSource { } } - /** - * A pragma token that should be handled in the parser (not in the lexer) - * Used to allow the lexer to ensure the preprocessor skips it the second time around. - **/ - public static class PragmaToken implements Token { - - /** The underlying pragma token. */ - private Token subToken; - - PragmaToken(Token subToken) { - this.subToken = subToken; - } - - @Override - public String getText() { - return subToken.getText(); - } - - @Override - public int getType() { - return subToken.getType(); - } - - @Override - public int getLine() { - return subToken.getLine(); - } - - @Override - public int getCharPositionInLine() { - return subToken.getCharPositionInLine(); - } - - @Override - public int getChannel() { - return subToken.getChannel(); - } - - @Override - public int getTokenIndex() { - return subToken.getTokenIndex(); - } - - @Override - public int getStartIndex() { - return subToken.getStartIndex(); - } - - @Override - public int getStopIndex() { - return subToken.getStopIndex(); - } - - @Override - public TokenSource getTokenSource() { - return subToken.getTokenSource(); - } - - @Override - public CharStream getInputStream() { - return subToken.getInputStream(); - } - } - - } diff --git a/src/main/kc/include/c64.h b/src/main/kc/include/c64.h index b4431709a..b1519dca9 100644 --- a/src/main/kc/include/c64.h +++ b/src/main/kc/include/c64.h @@ -31,6 +31,9 @@ char * const COLORRAM = 0xd800; // Color Ram char * const COLS = 0xd800; +// Default address of screen character matrix +char * const DEFAULT_SCREEN = 0x0c00; + // The CIA#1: keyboard matrix, joystick #1/#2 struct MOS6526_CIA * const CIA1 = 0xdc00; // The CIA#2: Serial bus, RS-232, VIC memory bank diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 1860e118a..e26bfc81b 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -2,12 +2,14 @@ package dk.camelot64.kickc.test; import dk.camelot64.kickc.CompileLog; import dk.camelot64.kickc.Compiler; +import dk.camelot64.kickc.SourceLoader; import dk.camelot64.kickc.asm.AsmProgram; import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.TargetCpu; import dk.camelot64.kickc.model.TargetPlatform; +import dk.camelot64.kickc.parser.CTargetPlatformParser; import kickass.KickAssembler; import kickass.nonasm.c64.CharToPetsciiConverter; import org.junit.AfterClass; @@ -42,10 +44,15 @@ public class TestPrograms { public TestPrograms() { } - //@Test - //public void testPlus4Define() throws IOException, URISyntaxException { - // compileAndCompare("plus4-define.c", log()); - //} + @Test + public void testPlatformPlus4Define() throws IOException, URISyntaxException { + compileAndCompare("platform-plus4-define.c"); + } + + @Test + public void testPlatformDefaultDefine() throws IOException, URISyntaxException { + compileAndCompare("platform-default-define.c"); + } @Test public void testIncludeDefine() throws IOException, URISyntaxException { @@ -4313,7 +4320,6 @@ public class TestPrograms { compiler.addIncludePath(stdIncludePath); compiler.addLibraryPath(stdLibPath); compiler.addTargetPlatformPath(stdPlatformPath); - compiler.initAsmFragmentSynthesizer(asmFragmentSynthesizer); if(upliftCombinations != null) { compiler.setUpliftCombinations(upliftCombinations); } @@ -4321,7 +4327,11 @@ public class TestPrograms { final Path filePath = Paths.get(fileName); files.add(filePath); Program program = compiler.getProgram(); - TargetPlatform.setTargetPlatform(TargetPlatform.DEFAULT_NAME, filePath, program, null); + + final File platformFile = SourceLoader.loadFile(TargetPlatform.DEFAULT_NAME + "." + CTargetPlatformParser.FILE_EXTENSION, filePath, program.getTargetPlatformPaths()); + final TargetPlatform targetPlatform = CTargetPlatformParser.parseTargetPlatformFile(TargetPlatform.DEFAULT_NAME, platformFile, filePath, program.getTargetPlatformPaths()); + program.setTargetPlatform(targetPlatform); + compiler.initAsmFragmentSynthesizer(asmFragmentSynthesizer); compiler.compile(files, program.getTargetPlatform().getDefines()); compileAsm(fileName, program); boolean success = true; diff --git a/src/test/kc/platform-default-define.c b/src/test/kc/platform-default-define.c new file mode 100644 index 000000000..bcb327169 --- /dev/null +++ b/src/test/kc/platform-default-define.c @@ -0,0 +1,11 @@ +// Test the #define for the default platform + +char* const SCREEN = 0x0400; + +void main() { + #ifdef __C64__ + SCREEN[0] = 'a'; + #else + SCREEN[0] = 'b'; + #endif +} diff --git a/src/test/kc/platform-plus4-define.c b/src/test/kc/platform-plus4-define.c new file mode 100644 index 000000000..8b576c69b --- /dev/null +++ b/src/test/kc/platform-plus4-define.c @@ -0,0 +1,12 @@ +// Test the #define for the plus4 target platform +#pragma target(plus4basic) + +char * const SCREEN = 0x0c00; + +void main() { + #ifdef __PLUS4__ + SCREEN[0] = 'a'; + #else + SCREEN[0] = 'b'; + #endif +} diff --git a/src/test/kc/plus4-define.c b/src/test/kc/plus4-define.c deleted file mode 100644 index f166e5f41..000000000 --- a/src/test/kc/plus4-define.c +++ /dev/null @@ -1,12 +0,0 @@ -// Test writing to the Plus/4 TED HSCAN_POS -#pragma target(plus4basic) - -#include - -void main() { - #ifdef __PLUS4__ - DEFAULT_SCREEN[0] = 'a'; - #else - DEFAULT_SCREEN[0] = 'b'; - #endif -} diff --git a/src/test/ref/platform-default-define.asm b/src/test/ref/platform-default-define.asm new file mode 100644 index 000000000..99b4ae123 --- /dev/null +++ b/src/test/ref/platform-default-define.asm @@ -0,0 +1,12 @@ +// Test the #define for the default platform +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 +main: { + // SCREEN[0] = 'a' + lda #'a' + sta SCREEN + // } + rts +} diff --git a/src/test/ref/platform-default-define.cfg b/src/test/ref/platform-default-define.cfg new file mode 100644 index 000000000..6a5142472 --- /dev/null +++ b/src/test/ref/platform-default-define.cfg @@ -0,0 +1,17 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' + to:main::@return +main::@return: scope:[main] from main + [5] return + to:@return diff --git a/src/test/ref/platform-default-define.log b/src/test/ref/platform-default-define.log new file mode 100644 index 000000000..a5df5752e --- /dev/null +++ b/src/test/ref/platform-default-define.log @@ -0,0 +1,216 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + *((const nomodify byte*) SCREEN + (number) 0) ← (byte) 'a' + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*)(number) $400 +(void()) main() +(label) main::@return + +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) SCREEN + (number) 0) ← (byte) 'a' +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Simplifying expression containing zero SCREEN in [0] *((const nomodify byte*) SCREEN + (byte) 0) ← (byte) 'a' +Successful SSA optimization PassNSimplifyExpressionWithZero +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' + to:main::@return +main::@return: scope:[main] from main + [5] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test the #define for the default platform + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + // [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' -- _deref_pbuc1=vbuc2 + lda #'a' + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [5] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' [ ] ( main:2 [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 27 combination +Uplifting [] best 27 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test the #define for the default platform + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + // [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' -- _deref_pbuc1=vbuc2 + lda #'a' + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [5] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1_from___bbegin: +Removing instruction __b1: +Removing instruction __bend_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bbegin: +Removing instruction __bend: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*) 1024 +(void()) main() +(label) main::@return + + + +FINAL ASSEMBLER +Score: 12 + + // File Comments +// Test the #define for the default platform + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + // SCREEN[0] = 'a' + // [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' -- _deref_pbuc1=vbuc2 + lda #'a' + sta SCREEN + // main::@return + // } + // [5] return + rts +} + // File Data + diff --git a/src/test/ref/platform-default-define.sym b/src/test/ref/platform-default-define.sym new file mode 100644 index 000000000..17d516eda --- /dev/null +++ b/src/test/ref/platform-default-define.sym @@ -0,0 +1,7 @@ +(label) @1 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*) 1024 +(void()) main() +(label) main::@return + diff --git a/src/test/ref/platform-plus4-define.asm b/src/test/ref/platform-plus4-define.asm new file mode 100644 index 000000000..86db7a0a0 --- /dev/null +++ b/src/test/ref/platform-plus4-define.asm @@ -0,0 +1,13 @@ +// Test the #define for the plus4 target platform +.pc = $1001 "Basic" +:BasicUpstart(main) +.pc = $100d "Program" + + .label SCREEN = $c00 +main: { + // SCREEN[0] = 'a' + lda #'a' + sta SCREEN + // } + rts +} diff --git a/src/test/ref/platform-plus4-define.cfg b/src/test/ref/platform-plus4-define.cfg new file mode 100644 index 000000000..6a5142472 --- /dev/null +++ b/src/test/ref/platform-plus4-define.cfg @@ -0,0 +1,17 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' + to:main::@return +main::@return: scope:[main] from main + [5] return + to:@return diff --git a/src/test/ref/platform-plus4-define.log b/src/test/ref/platform-plus4-define.log new file mode 100644 index 000000000..824796057 --- /dev/null +++ b/src/test/ref/platform-plus4-define.log @@ -0,0 +1,219 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + *((const nomodify byte*) SCREEN + (number) 0) ← (byte) 'a' + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*)(number) $c00 +(void()) main() +(label) main::@return + +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) SCREEN + (number) 0) ← (byte) 'a' +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (byte*) 3072 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Simplifying expression containing zero SCREEN in [0] *((const nomodify byte*) SCREEN + (byte) 0) ← (byte) 'a' +Successful SSA optimization PassNSimplifyExpressionWithZero +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' + to:main::@return +main::@return: scope:[main] from main + [5] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is plus4basic / MOS6502X + // File Comments +// Test the #define for the plus4 target platform + // Upstart +.pc = $1001 "Basic" +:BasicUpstart(main) +.pc = $100d "Program" + + // Global Constants & labels + .label SCREEN = $c00 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + // [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' -- _deref_pbuc1=vbuc2 + lda #'a' + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [5] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' [ ] ( main:2 [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 27 combination +Uplifting [] best 27 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test the #define for the plus4 target platform + // Upstart +.pc = $1001 "Basic" +:BasicUpstart(main) +.pc = $100d "Program" + + // Global Constants & labels + .label SCREEN = $c00 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + // [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' -- _deref_pbuc1=vbuc2 + lda #'a' + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [5] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1_from___bbegin: +Removing instruction __b1: +Removing instruction __bend_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bbegin: +Removing instruction __bend: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*) 3072 +(void()) main() +(label) main::@return + + + +FINAL ASSEMBLER +Score: 12 + + // File Comments +// Test the #define for the plus4 target platform + // Upstart +.pc = $1001 "Basic" +:BasicUpstart(main) +.pc = $100d "Program" + + // Global Constants & labels + .label SCREEN = $c00 + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + // SCREEN[0] = 'a' + // [4] *((const nomodify byte*) SCREEN) ← (byte) 'a' -- _deref_pbuc1=vbuc2 + lda #'a' + sta SCREEN + // main::@return + // } + // [5] return + rts +} + // File Data + diff --git a/src/test/ref/platform-plus4-define.sym b/src/test/ref/platform-plus4-define.sym new file mode 100644 index 000000000..f425209c8 --- /dev/null +++ b/src/test/ref/platform-plus4-define.sym @@ -0,0 +1,7 @@ +(label) @1 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*) 3072 +(void()) main() +(label) main::@return +