public FieldSRef BaseField() { if (Program.CurrentFunction.localints.ContainsKey(name)) { return(FieldSRef.LocalInt(Program.CurrentFunction.name, name)); } else { return(FieldSRef.GlobalInt(name)); } }
public List <Instruction> BuildFunction() { var b = new List <Instruction>(); // save call site (in r8.signal-0) b.Add(new Push(RegVRef.rScratchInts)); if (localints.Count > 0) { // save parent localints b.Add(new Push(RegVRef.rLocalInts("parent"))); } // push regs as needed foreach (var sym in locals.Where(s => s.type == SymbolType.Register)) { if (sym.fixedAddr.HasValue) { b.Add(new Push(new RegVRef(sym.fixedAddr.Value))); } } // wind stack down for locals if needed if (framesize > 0) { b.Add(new Instruction { opcode = Opcode.Add, op1 = FieldSRef.Imm1(), imm1 = new IntSExpr(-framesize), acc = true, dest = FieldSRef.Pointer(PointerIndex.CallStack) }); } // copy params if named //int args or null in r8 var intparas = locals.Where(sym => sym.type == SymbolType.Parameter && sym.datatype == "int").ToList(); if (intparas.Count() > 0) { for (int i = 0; i < intparas.Count(); i++) { b.Add(new Instruction { opcode = Opcode.Add, op1 = FieldSRef.IntArg(name, intparas[i].name), dest = FieldSRef.LocalInt(name, intparas[i].name), acc = i != 0, }); } } FieldSRef.ResetScratchInts(); b.AddRange(RegVRef.rScratchInts.PutFromReg(RegVRef.rNull)); // body b.AddRange(body.CodeGen()); // convert rjmp __return => rjmp <integer> to here. for (int i = 0; i < b.Count; i++) { var inst = b[i]; if ((inst.imm1 as AddrSExpr)?.symbol == "__return") { inst.imm1 = new IntSExpr(b.Count - i); } if ((inst.imm2 as AddrSExpr)?.symbol == "__return") { inst.imm2 = new IntSExpr(b.Count - i); } b[i] = inst; } // wind stack back up for locals if needed if (framesize > 0) { b.Add(new Instruction { opcode = Opcode.Add, op1 = FieldSRef.Imm1(), imm1 = new IntSExpr(framesize), acc = true, dest = FieldSRef.Pointer(PointerIndex.CallStack) }); } // restore registers foreach (var sym in locals.Where(s => s.type == SymbolType.Register).Reverse()) { if (sym.fixedAddr.HasValue) { b.Add(new Pop(new RegVRef(sym.fixedAddr.Value))); } } if (localints.Count > 0) { // restore parent localints b.Add(new Pop(RegVRef.rLocalInts("parent"))); } // get return site b.Add(new Exchange(RegVRef.rScratchTab)); b.Add(new Instruction { opcode = Opcode.Sub, op1 = FieldSRef.VarField(RegVRef.rScratchTab, "signal-0"), op2 = FieldSRef.CallSite, dest = FieldSRef.CallSite, acc = true }); b.Add(new Pop(RegVRef.rScratchTab)); // jump to return site b.Add(new Jump { target = FieldSRef.CallSite }); return(b); }