ttir and qbe: added function calls

This commit is contained in:
Robin Bärtschi 2025-03-12 21:31:14 +01:00
parent b57ec5f5cf
commit 9cfb80e790
5 changed files with 68 additions and 39 deletions

View File

@ -22,7 +22,12 @@ func extraLabel() string {
var Stub string
func emitf(w io.Writer, format string, args ...any) error {
_, err := w.Write([]byte(fmt.Sprintf(format, args...)))
_, err := w.Write(fmt.Appendf(nil, format, args...))
return err
}
func emit(w io.Writer, content string) error {
_, err := w.Write(fmt.Append(nil, content))
return err
}
@ -101,14 +106,9 @@ func emitInstruction(w io.Writer, i ttir.Instruction) error {
switch i := i.(type) {
case *ttir.Ret:
if op := i.Op; op != nil {
if err := emitf(w, "\tret %s\n", emitOperand(i.Op)); err != nil {
return err
}
return emitf(w, "\tret %s\n", emitOperand(i.Op))
} else {
if err := emitf(w, "\tret\n"); err != nil {
return err
}
return emitf(w, "\tret\n")
}
case *ttir.Binary:
var inst string
@ -134,31 +134,36 @@ func emitInstruction(w io.Writer, i ttir.Instruction) error {
case ast.LessThanEqual:
inst = "cslel"
}
if err := emitf(w, "\t%s =l %s %s, %s\n", emitOperand(i.Dst), inst, emitOperand(i.Lhs), emitOperand(i.Rhs)); err != nil {
return err
}
return emitf(w, "\t%s =l %s %s, %s\n", emitOperand(i.Dst), inst, emitOperand(i.Lhs), emitOperand(i.Rhs))
case *ttir.Copy:
if err := emitf(w, "\t%s =l copy %s\n", emitOperand(i.Dst), emitOperand(i.Src)); err != nil {
return err
}
emitf(w, "\t%s =l copy %s\n", emitOperand(i.Dst), emitOperand(i.Src))
case ttir.Label:
if err := emitf(w, "@%s\n", string(i)); err != nil {
return err
}
return emitf(w, "@%s\n", string(i))
case ttir.Jump:
if err := emitf(w, "\tjmp @%s\n", string(i)); err != nil {
return err
}
return emitf(w, "\tjmp @%s\n", string(i))
case *ttir.JumpIfNotZero:
after := extraLabel()
if err := emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), i.Label, after, after); err != nil {
return err
}
return emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), i.Label, after, after)
case *ttir.JumpIfZero:
after := extraLabel()
if err := emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), after, i.Label, after); err != nil {
return err
return emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), after, i.Label, after)
case *ttir.Call:
b := strings.Builder{}
b.WriteRune('\t')
if i.ReturnValue != nil {
b.WriteString(emitOperand(i.ReturnValue) + " =l ")
}
b.WriteString("call $" + i.FunctionName + "(")
for j, arg := range i.Arguments {
b.WriteString("l " + emitOperand(arg))
if j < (len(i.Arguments) - 1) {
b.WriteString(", ")
}
}
b.WriteString(")\n")
return emit(w, b.String())
default:
panic("unkown instruction")
}

View File

@ -454,6 +454,10 @@ func (p *Parser) parseFunctionCall() ast.Expression {
p.nextToken()
args = append(args, p.parseExpression(PrecLowest))
if !p.peekTokenIs(token.Comma) {
break
}
p.nextToken()
}
// Move onto the ')'

17
test.tt
View File

@ -1,17 +1,12 @@
fn main(): i64 = {
i := 5;
test2(3, 0)
};
if i == 5 {
fn test2(until: i64, i: i64): i64 = {
if i >= until {
0
} else {
1
};
test2(3)
};
fn test2(hello: i64): i64 = {
hello // Comment test
test2(until, i+1) + 1
}
};

View File

@ -148,6 +148,24 @@ func emitExpression(expr tast.Expression) (Operand, []Instruction) {
return nil, instructions
case *tast.VariableReference:
return &Var{Value: expr.Identifier}, []Instruction{}
case *tast.FunctionCall:
var dst Operand
if !expr.ReturnType.IsSameType(types.Unit) {
dst = &Var{Value: temp()}
}
args := []Operand{}
instructions := []Instruction{}
for _, arg := range expr.Arguments {
dst, argInstructions := emitExpression(arg)
instructions = append(instructions, argInstructions...)
args = append(args, dst)
}
instructions = append(instructions, &Call{FunctionName: expr.Identifier, Arguments: args, ReturnValue: dst})
return dst, instructions
default:
panic(fmt.Sprintf("unexpected tast.Expression: %#v", expr))
}

View File

@ -117,15 +117,20 @@ func (l Label) String() string {
func (l Label) instruction() {}
type Call struct {
Label string
Arguments []Operand
FunctionName string
Arguments []Operand
// NOTE: Nullable
ReturnValue Operand
}
func (c *Call) String() string {
b := strings.Builder{}
b.WriteString(c.ReturnValue.String() + " = call " + c.Label + " ")
if c.ReturnValue != nil {
b.WriteString(c.ReturnValue.String() + " = ")
}
b.WriteString("call " + c.FunctionName + " ")
for i, arg := range c.Arguments {
b.WriteString(arg.String())
@ -135,6 +140,8 @@ func (c *Call) String() string {
}
}
b.WriteRune('\n')
return b.String()
}
func (c *Call) instruction() {}