ch2-expr/ch2-02-mul-div #22
Replies: 2 comments
-
package main
import (
"fmt"
"os"
"bytes"
"io"
"os/exec"
)
type ExprNode struct {
Value string // +, -, *, /, 123
Left *ExprNode
Right *ExprNode
}
type Compiler struct {
nextId int
}
func (p *Compiler) genValue(w io.Writer, node *ExprNode) (id string) {
if node == nil {
return ""
}
id = p.genId()
switch node.Value {
case "+":
fmt.Fprintf(w, "\t%s = add i32 %s, %s\n",
id, p.genValue(w, node.Left), p.genValue(w, node.Right),
)
case "-":
fmt.Fprintf(w, "\t%s = sub i32 %s, %s\n",
id, p.genValue(w, node.Left), p.genValue(w, node.Right),
)
case "*":
fmt.Fprintf(w, "\t%s = mul i32 %s, %s\n",
id, p.genValue(w, node.Left), p.genValue(w, node.Right),
)
case "/":
fmt.Fprintf(w, "\t%s = sdiv i32 %s, %s\n",
id, p.genValue(w, node.Left), p.genValue(w, node.Right),
)
default:
fmt.Fprintf(w, "\t%[1]s = add i32 0, %[2]s; %[1]s = %[2]s\n",
id, node.Value,
)
}
return
}
func (p *Compiler) GenLLIR(node *ExprNode) string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "define i32 @main() {\n")
fmt.Fprintf(&buf, " ret i32 %s\n", p.genValue(&buf, node))
fmt.Fprintf(&buf, "}\n")
return buf.String()
}
func (p *Compiler) genId() string {
id := fmt.Sprintf("%%t%d", p.nextId)
p.nextId++
return id
}
func compile(code *ExprNode) {
c := Compiler{}
output := c.GenLLIR(code)
fmt.Println(output)
os.WriteFile("a.out.ll", []byte(output), 0666)
exec.Command("clang", "-Wno-override-module", "-o", "a.out", "a.out.ll").Run()
}
func run(code *ExprNode) int {
compile(code)
if err := exec.Command("./a.out").Run(); err != nil {
return err.(*exec.ExitError).ExitCode()
}
return 0
}
func main() {
var expr = &ExprNode{
Value: "+",
Left: &ExprNode{
Value: "1",
},
Right: &ExprNode{
Value: "*",
Left: &ExprNode{
Value: "2",
},
Right: &ExprNode{
Value: "+",
Left: &ExprNode{
Value: "3",
},
Right: &ExprNode{
Value: "4",
},
},
},
}
result := run(expr)
fmt.Println(result)
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
package main
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
)
type ExprNode struct {
value string // + - * / 1 2 ...
left *ExprNode
right *ExprNode
}
// 1 + 2 * (3 + 4) 的语法树
var expr = ExprNode{
value: "+",
left: &ExprNode{
value: "1",
},
right: &ExprNode{
value: "*",
left: &ExprNode{
value: "2",
},
right: &ExprNode{
value: "+",
left: &ExprNode{
value: "3",
},
right: &ExprNode{
value: "4",
},
},
},
}
// 构造Expr的Compiler对象
type Compiler struct {
nextregisterid int
}
func (p *Compiler) GenLLIR(node *ExprNode) string {
var buf bytes.Buffer // Buffer是存放字节的一个结构体
fmt.Fprintf(&buf, "define i32 @main() {\n")
fmt.Fprintf(&buf, "\tret i32 %s\n", p.genValue(&buf, node))
fmt.Fprintf(&buf, "}\n")
return buf.String()
}
func (p *Compiler) genId() string {
id := fmt.Sprintf("%%t%d", p.nextregisterid)
p.nextregisterid++
return id
}
// 表达式的终极节点通过p.genValue(&buf, node)完成编译
func (p *Compiler) genValue(w io.Writer, node *ExprNode) string {
id := p.genId() // 获得这一行的寄存器编号
switch node.value {
case "+":
fmt.Fprintf(w, "\t%v = add i32 %v, %v\n", id, p.genValue(w, node.left), p.genValue(w, node.right))
case "-":
fmt.Fprintf(w, "\t%v = sub i32 %v, %v\n", id, p.genValue(w, node.left), p.genValue(w, node.right))
case "*":
fmt.Fprintf(w, "\t%v = mul i32 %v, %v\n", id, p.genValue(w, node.left), p.genValue(w, node.right))
case "/":
fmt.Fprintf(w, "\t%v = sdiv i32 %v, %v\n", id, p.genValue(w, node.left), p.genValue(w, node.right))
default: // 终止递归的条件
fmt.Fprintf(w, "\t%v = add i32 0, %v\n", id, node.value)
}
return id
}
func run() int {
// 编译
var compiler Compiler
llir := compiler.GenLLIR(&expr)
// 保存
os.WriteFile("2.2.out.ll", []byte(llir), 0666)
// 汇编
result, err := exec.Command("clang", "-Wno-override-module", "-o", "2.2.out", "2.2.out.ll").CombinedOutput()
if err != nil {
fmt.Printf("汇编错误:\n%v\n", err.Error())
fmt.Printf("错误信息:\n%v", string(result))
return -1
}
// 运行
if err := exec.Command("./2.2.out").Run(); err != nil {
return err.(*exec.ExitError).ExitCode() // 断言
}
return -1
}
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
ch2-expr/ch2-02-mul-div
如何从头开发一个迷你Go语言编译器
https://wa-lang.org/ugo-compiler-book/ch2-expr/ch2-02-mul-div.html
Beta Was this translation helpful? Give feedback.
All reactions