summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorElias Haugsbakk <[email protected]>2026-09-18 00:13:13 +0200
committerElias Haugsbakk <[email protected]>2026-09-18 00:13:13 +0200
commitc7363c58612b7d3183c0ee91d5eee166fd515758 (patch)
tree175dfd722168a51c446da7f3a971f4464a3be30b /src/main/java
parent30b415615740939a7522a20f222699a30f89a22e (diff)
implement print("String") for IR to assembly translation
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/no/eliashaugsbakk/kompilator/AssemblyBuilder.java95
-rw-r--r--src/main/java/no/eliashaugsbakk/kompilator/Main.java62
2 files changed, 126 insertions, 31 deletions
diff --git a/src/main/java/no/eliashaugsbakk/kompilator/AssemblyBuilder.java b/src/main/java/no/eliashaugsbakk/kompilator/AssemblyBuilder.java
new file mode 100644
index 0000000..4e89590
--- /dev/null
+++ b/src/main/java/no/eliashaugsbakk/kompilator/AssemblyBuilder.java
@@ -0,0 +1,95 @@
+package no.eliashaugsbakk.kompilator;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AssemblyBuilder {
+ Map<String, String> stringVariables = new HashMap<>();
+
+ StringBuilder finalAssembly;
+ StringBuilder text;
+ StringBuilder rodata;
+ StringBuilder data;
+
+
+ private final static String exit = """
+ mov rax, 60
+ xor rdi, rdi
+ syscall
+ """;
+
+ private final static String printHelloWorld = """
+ mov rax, 1
+ mov rdi, 1
+ lea rsi, [hellostring]
+ lea rdx, [hellolen]
+ syscall
+ """;
+
+ public AssemblyBuilder() {
+ this.finalAssembly = new StringBuilder(".intel_syntax noprefix\n.global _start\n");
+ // CPU instructions
+ this.text = new StringBuilder(".text\n_start:\n\n");
+ // Read only data
+ this.rodata = new StringBuilder("\n.section .rodata\n");
+ // Global initialized variables, Read - Write
+ this.data = new StringBuilder("\n.data\n");
+ }
+
+ String createAssembly(List<String> IR) {
+ for (String line : IR) {
+ line = line.trim();
+
+ if (line.startsWith("print")) {
+ handlePrint(line);
+ } else if (line.contains("=")) {
+ handleAssignment(line);
+ }
+ }
+ this.text.append(exit);
+ this.finalAssembly.append(text);
+ this.finalAssembly.append(rodata);
+ this.finalAssembly.append(data);
+ return this.finalAssembly.toString();
+ }
+
+ private void handleAssignment(String line) {
+ /* Example IR:
+ variable_name: type = data
+ str1: string = "Hello world"
+ */
+ String name = line.substring(0, line.indexOf(":"));
+
+ String dataType = line.substring(line.indexOf(":") + 2, line.indexOf("=") - 1);
+
+ String value = line.substring(line.indexOf("=") + 2);
+
+ if (dataType.contains("string")) {
+ assignString(name, value);
+ } else {
+ IO.println("err: Unknown data type: " + dataType);
+ }
+ }
+
+ private void assignString(String name, String value) {
+ value = value.substring(1, value.length() - 1);
+ this.rodata.append(String.format("""
+ %s: .ascii "%s"
+ """, name, value));
+ this.stringVariables.put(name, value);
+ }
+
+ void handlePrint(String line) {
+ String variableName = line.substring(line.indexOf("(") + 1, line.lastIndexOf(")"));
+
+ this.text.append(String.format("""
+ mov rax, 1
+ mov rdi, 1
+ lea rsi, [%s]
+ lea rdx, [%d]
+ syscall
+
+ """, variableName, this.stringVariables.get(variableName).length()));
+ }
+}
diff --git a/src/main/java/no/eliashaugsbakk/kompilator/Main.java b/src/main/java/no/eliashaugsbakk/kompilator/Main.java
index f57b13a..be5746c 100644
--- a/src/main/java/no/eliashaugsbakk/kompilator/Main.java
+++ b/src/main/java/no/eliashaugsbakk/kompilator/Main.java
@@ -8,39 +8,41 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.List;
public class Main {
public static final String programFileExtension = "spå";
- private record InputProgram(String programName, String programContent) {}
+
+ private record InputProgram(String programName, String programContent) {
+ }
static void main(String[] args) {
if (args.length != 1) {
- IO.println("Only accepts one argument: The filename of the input program");
+ IO.println("err: Only accepts one argument: The filename of the input program");
System.exit(1);
}
InputProgram inputProgram = readInputProgram(args[0]);
- /*
- String IR = createIR(inputFile);
- String assembly = createAssembly(IR);
- */
+ List<String> IR = List.of();
- assemblingAndLInking(inputProgram);
+ String assembly = new AssemblyBuilder().createAssembly(IR);
+
+ assemblingAndLInking(inputProgram.programName(), assembly);
System.exit(0);
}
- private static void assemblingAndLInking(InputProgram inputProgram) {
- String assemblyFileName = inputProgram.programName + ".s";
- String assembledFileName = inputProgram.programContent + ".o";
+ private static void assemblingAndLInking(String programName, String assembly) {
+ String assemblyFileName = programName + ".s";
+ String assembledFileName = programName + ".o";
try {
FileWriter fw = new FileWriter(assemblyFileName);
- fw.write(inputProgram.programContent);
+ fw.write(assembly);
fw.close();
} catch (IOException e) {
- IO.println("Could not write file: " + e.getMessage());
+ IO.println("err: Could not write file: " + e.getMessage());
}
try {
@@ -48,39 +50,41 @@ public class Main {
ProcessBuilder asPB = new ProcessBuilder("as", "-o", assembledFileName, assemblyFileName);
runProcess(asPB);
} catch (IOException e) {
- IO.println("Failed to invoke GCC\n\n" + e);
+ IO.println("err: Failed to invoke GCC\n\n" + e);
} catch (InterruptedException e) {
- IO.println("Failed to wait for gcc output\n\n" + e);
+ IO.println("err: Failed to wait for gcc output\n\n" + e);
}
try {
// Linking using GNU linker: ld -o program program.o
- ProcessBuilder ldPB = new ProcessBuilder("ld", "-o", inputProgram.programName, assembledFileName);
+ ProcessBuilder ldPB = new ProcessBuilder("ld", "-o", programName, assembledFileName);
runProcess(ldPB);
} catch (IOException e) {
- IO.println("Failed to invoke GCC\n\n" + e);
+ IO.println("err: Failed to invoke GCC\n\n" + e);
} catch (InterruptedException e) {
- IO.println("Failed to wait for gcc output\n\n" + e);
+ IO.println("err: Failed to wait for gcc output\n\n" + e);
}
// Clean up
try {
Files.delete(Path.of(assemblyFileName));
} catch (IOException e) {
- IO.println("Could not delete assembly file: " + e.getMessage());
+ IO.println("err: Could not delete assembly file: " + e.getMessage());
}
try {
Files.delete(Path.of(assembledFileName));
} catch (IOException e) {
- IO.println("Could not delete assembled file: " + e.getMessage());
+ IO.println("err: Could not delete assembled file: " + e.getMessage());
}
}
- private static void runProcess(ProcessBuilder processBuilder) throws IOException, InterruptedException {
+ private static void runProcess(ProcessBuilder processBuilder)
+ throws IOException, InterruptedException {
Process process = processBuilder.start();
process.waitFor();
if (process.exitValue() != 0) {
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+ BufferedReader bufferedReader =
+ new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
@@ -91,21 +95,17 @@ public class Main {
}
private static InputProgram readInputProgram(String inputFilePath) {
- IO.println("Input file path: " + inputFilePath);
-
if (!inputFilePath.endsWith("." + programFileExtension)) {
- IO.println("Input file must use the file extension: " + programFileExtension);
+ IO.println("err: Input file must use the file extension: " + programFileExtension);
System.exit(1);
}
- String programName = inputFilePath.substring(
- inputFilePath.lastIndexOf("/") + 1,
- inputFilePath.lastIndexOf("."));
- IO.println("Program name: " + programName);
+ String programName =
+ inputFilePath.substring(inputFilePath.lastIndexOf("/") + 1, inputFilePath.lastIndexOf("."));
String programContent = null;
- try(BufferedReader br = new BufferedReader(new FileReader(inputFilePath))) {
+ try (BufferedReader br = new BufferedReader(new FileReader(inputFilePath))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
@@ -116,13 +116,13 @@ public class Main {
}
programContent = sb.toString();
} catch (FileNotFoundException e) {
- IO.println("File not found");
+ IO.println("err: File not found");
} catch (IOException e) {
IO.println(e.getMessage());
}
if (programContent == null) {
- IO.println("Could not read input file");
+ IO.println("err: Could not read input file");
System.exit(1);
}