From 2f9d42d4ad91a0f836c84bfdcb84d301803347a0 Mon Sep 17 00:00:00 2001 From: Laborratte5 Date: Mon, 19 May 2025 21:55:57 +0200 Subject: [PATCH] Implement liveness analysis --- .../backend/x86asm/X68RegisterAllocator.java | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 src/main/java/edu/kit/kastel/vads/compiler/backend/x86asm/X68RegisterAllocator.java diff --git a/src/main/java/edu/kit/kastel/vads/compiler/backend/x86asm/X68RegisterAllocator.java b/src/main/java/edu/kit/kastel/vads/compiler/backend/x86asm/X68RegisterAllocator.java new file mode 100644 index 0000000..72d1acb --- /dev/null +++ b/src/main/java/edu/kit/kastel/vads/compiler/backend/x86asm/X68RegisterAllocator.java @@ -0,0 +1,141 @@ +package edu.kit.kastel.vads.compiler.backend.x86asm; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.stream.Collectors; + +import edu.kit.kastel.vads.compiler.backend.regalloc.Register; +import edu.kit.kastel.vads.compiler.backend.regalloc.RegisterAllocator; +import edu.kit.kastel.vads.compiler.ir.IrGraph; +import edu.kit.kastel.vads.compiler.ir.node.BinaryOperationNode; +import edu.kit.kastel.vads.compiler.ir.node.Block; +import edu.kit.kastel.vads.compiler.ir.node.ConstIntNode; +import edu.kit.kastel.vads.compiler.ir.node.Node; +import edu.kit.kastel.vads.compiler.ir.node.ProjNode; +import edu.kit.kastel.vads.compiler.ir.node.ReturnNode; +import edu.kit.kastel.vads.compiler.ir.node.StartNode; + +public class X68RegisterAllocator implements RegisterAllocator { + + private class InterferenceGraph { + + } + + private final Map> temps; + private int nextTemp; + + public X68RegisterAllocator() { + temps = new HashMap<>(); + nextTemp = 0; + } + + @Override + public Map allocateRegisters(IrGraph graph) { + analyseLive(graph); + + System.out.println("====="); + printTemps(); + throw new UnsupportedOperationException(); + //InterferenceGraph interference = buildInterferenceGraph(temps); + //return allocateRegisters(interference); + } + + private void analyseLive(IrGraph graph) { + boolean change = false; + do { + change = analyseLiveSinglePass(graph.endBlock(), new HashSet<>()); + } while (change); + } + + private boolean analyseLiveSinglePass(Node node, Set visited) { + boolean changed = false; + + if (needsRegister(node)) { + // Get Live Out of node + Set liveOut = temps.getOrDefault(node, Set.of()); + + Set kill = getKillOf(node); + Set gen = getGenOf(node); + + Set liveIn = new HashSet<>(liveOut); + liveIn.removeAll(kill); + liveIn.addAll(gen); + + Set old = temps.put(node, liveIn); + changed |= old == null || !old.equals(liveIn); + + //if (changed) { + System.out.println("Node " + node); + System.out.println("Out: " + Arrays.toString(liveOut.toArray())); + System.out.println("Kill: " + Arrays.toString(kill.toArray())); + System.out.println("Gen: " + Arrays.toString(gen.toArray())); + System.out.println("In: " + Arrays.toString(liveIn.toArray())); + System.out.println(); + //printTemps(); + //System.out.println(); + //} + + } + + for (Node predecessor : node.predecessors()) { + if (visited.add(predecessor)) { + changed |= analyseLiveSinglePass(predecessor, visited); + } + } + + return changed; + } + + private Set getSuccessors(Node node) { + return node.graph().successors(node); + } + + private InterferenceGraph buildInterferenceGraph(Map> temps) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'buildInterferenceGraph'"); + } + + private Map allocateRegisters(InterferenceGraph graph) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'allocateRegisters'"); + } + + private static boolean needsRegister(Node node) { + return !(node instanceof ProjNode || node instanceof StartNode || node instanceof Block); + } + + private Set getKillOf(Node node) { + return switch (node) { + case BinaryOperationNode bin -> Set.of(bin); + case ConstIntNode c -> Set.of(c); + case ReturnNode _ -> Set.of(); + default -> throw new UnsupportedOperationException("No 'kill' set for " + node + "implemented."); + }; + } + + private Set getGenOf(Node node) { + return switch (node) { + // TODO special case div/mod + case BinaryOperationNode bin -> Set.of(bin.predecessor(BinaryOperationNode.LEFT), bin.predecessor(BinaryOperationNode.RIGHT)); + case ConstIntNode _ -> Set.of(); + case ReturnNode ret -> Set.of(ret.predecessor(ReturnNode.RESULT)); + default -> throw new UnsupportedOperationException("No 'kill' set for " + node + "implemented."); + }; + } + + private void printTemps() { + + for (Entry> e : temps.entrySet()) { + //System.out.println(e.getValue().size()); + System.out.println(e.getKey() + ": " + e.getValue().stream().map(r -> String.valueOf(r.hashCode())).collect(Collectors.joining(", "))); + } + + } + +}