Instructions

Brez spremembe interpreterja spremenite svoj prevajalnik tako, da funkcija shrani povratni naslov le, če je to res potrebno.

Test

fun putint(c: int): void
fun putchar(c: char): void
fun puts(s: ^char): void

fun leaf(): int =
    return 0

fun nonLeaf(): int =
    return leaf()

fun main(): int =
    return leaf()

Out

Glej asm

Code

/memory/MEM.java

public class MEM {
    // ... other code ...
    public static class Frame {
        // ... other code ...
        public final boolean isLeaf;
	// ... other code ...
        public Frame(Label label, long depth, long locsSize, long argsSize, long size, boolean isLeaf) {
            this.label = label;
            this.depth = depth;
            this.locsSize = locsSize;
            this.argsSize = argsSize;
            this.size = size;
// --- ADDED: Store leaf property ---
            this.isLeaf = isLeaf;
            this.FP = new Temp();
            this.RV = new Temp();
        }
        // ... other code ...
    }
}

/memory/MemEvaluator.java

public class MemEvaluator implements AST.FullVisitor<Object, MemEvaluator.Info> {
    // ... other code ...
    private static class Info {
        // ... other code ...
// --- ADDED: Track if current function is a leaf ---
        private boolean isLeaf;
        // ... other code ...
        public Info() {
            // ... other code ...
// --- ADDED: Initialize isLeaf ---
            isLeaf = false;
            // ... other code ...
        }
    }
    // ... other code ...
 
    @Override
    public Object visit(AST.DefFunDefn defFunDefn, Info info) {
        long previousLocalsSize = info.localsSize; info.localsSize = 0L;
        long previousArgsSize = info.argsSize; info.argsSize = 0L;
// --- ADDED: Assume leaf at start ---
        boolean previousIsLeaf = info.isLeaf; info.isLeaf = true;
 
        defFunDefn.type.accept(this, info);
 
        long previousOffset = info.offset; info.offset = 0L;
        long previousDepth = info.depth; info.depth = Memory.frames.size();
        defFunDefn.pars.accept(this, info);
        defFunDefn.stmts.accept(this, info);
        info.offset = previousOffset;
        info.depth = previousDepth;
 
        long frameSize = info.localsSize + info.argsSize + 8L + 8L;
 
        MEM.Label frameLabel = info.depth == 0 ? new MEM.Label(defFunDefn.name) : new MEM.Label();
        MEM.Frame frame = new MEM.Frame(frameLabel, info.depth, info.localsSize, info.argsSize, frameSize, info.isLeaf);
// --- DEBUG: Print leaf status ---
        System.out.println("DEBUG: " + defFunDefn.name + " isLeaf: " + info.isLeaf);
        Memory.frames.put(defFunDefn, frame);
 
        info.offset = previousOffset;
        info.localsSize = previousLocalsSize;
        info.argsSize = previousArgsSize;
// --- RESTORE: Previous isLeaf state ---
        info.isLeaf = previousIsLeaf;
 
        return null;
    }
 
    // ... other code ...
 
    @Override
    public Object visit(AST.CallExpr callExpr, Info info) {
// --- ADDED: Any call means function is not a leaf ---
        info.isLeaf = false;
        callExpr.funExpr.accept(this, info);
        callExpr.argExprs.accept(this, info);
        return null;
    }
}

/asmdump/AsmDump.java

// ... other code ...
long raOffset = codeChunk.frame.locsSize + 16;
String saveReturnAddress = ASM.SD_INSTR
    .replace("$s0", "ra")
    .replace("$offset", Long.toString(-raOffset))
    .replace("$s1", "sp");
 
// --- ADDED: Do not save return address for leaf functions ---
if (codeChunk.frame.isLeaf) saveReturnAddress = "";
 
// ... other code ...
 
String restoreReturnAddress = ASM.LD_INSTR
    .replace("$s1", "ra")
    .replace("$offset", Long.toString(-raOffset))
    .replace("$s0", "s0");
 
// --- ADDED: Do not restore return address for leaf functions ---
if (codeChunk.frame.isLeaf) restoreReturnAddress = "";