mirror of
https://gitee.com/wa-lang/wa.git
synced 2025-12-06 09:18:53 +08:00
完善 p9asm
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,6 +11,7 @@ wa.exe
|
||||
*.exe
|
||||
*.dll
|
||||
*.a
|
||||
*.o
|
||||
*.so
|
||||
*.dylib
|
||||
*.out*
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
package appp9asm
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"wa-lang.org/wa/internal/3rdparty/cli"
|
||||
@@ -18,7 +20,7 @@ import (
|
||||
var CmdP9Asm = &cli.Command{
|
||||
Hidden: true,
|
||||
Name: "p9asm",
|
||||
Usage: "plan9 assembly language tool",
|
||||
Usage: "p9asm language assembly tool",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
@@ -70,6 +72,28 @@ var CmdP9Asm = &cli.Command{
|
||||
arch := arch.Set(arch.AMD64)
|
||||
ctxt := obj.Linknew(&x86.Linkamd64)
|
||||
|
||||
if flags.PrintOut {
|
||||
ctxt.Debugasm = 1
|
||||
}
|
||||
ctxt.LineHist.TrimPathPrefix = flags.TrimPath
|
||||
ctxt.Flag_dynlink = flags.Dynlink
|
||||
if flags.Shared || flags.Dynlink {
|
||||
ctxt.Flag_shared = 1
|
||||
}
|
||||
|
||||
fd, err := os.Create(flags.OutputFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ctxt.Bso = obj.Binitw(os.Stdout)
|
||||
defer ctxt.Bso.Flush()
|
||||
|
||||
ctxt.Diag = log.Fatalf
|
||||
output := obj.Binitw(fd)
|
||||
fmt.Fprintf(output, "wa object %s %s\n", obj.Getgoos(), obj.Getwaarch())
|
||||
fmt.Fprintf(output, "!\n")
|
||||
|
||||
lexer, err := lex.NewLexer(name, ctxt, flags)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
@@ -77,13 +101,16 @@ var CmdP9Asm = &cli.Command{
|
||||
}
|
||||
parser := asm.NewParser(ctxt, arch, lexer, flags)
|
||||
|
||||
prog, ok := parser.Parse()
|
||||
pList := obj.Linknewplist(ctxt)
|
||||
var ok bool
|
||||
pList.Firstpc, ok = parser.Parse()
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "asm: assembly of %s failed", c.Args().First())
|
||||
log.Printf("asm: assembly of %s failed", flag.Arg(0))
|
||||
os.Remove(flags.OutputFile)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("%+v\n", prog)
|
||||
obj.Writeobjdirect(ctxt, output)
|
||||
output.Flush()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
72
internal/app/appp9link/appp9link.go
Normal file
72
internal/app/appp9link/appp9link.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2024 武汉凹语言科技有限公司
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
package appp9link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"wa-lang.org/wa/internal/3rdparty/cli"
|
||||
"wa-lang.org/wa/internal/p9asm/link/amd64"
|
||||
"wa-lang.org/wa/internal/p9asm/link/arm"
|
||||
"wa-lang.org/wa/internal/p9asm/link/arm64"
|
||||
"wa-lang.org/wa/internal/p9asm/link/x86"
|
||||
"wa-lang.org/wa/internal/p9asm/obj"
|
||||
)
|
||||
|
||||
var CmdP9Link = &cli.Command{
|
||||
Hidden: true,
|
||||
Name: "p9link",
|
||||
Usage: "p9asm object link tool",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "dump instructions as they are parsed",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "o",
|
||||
Usage: "output file; default foo.6 for /a/b/c/foo.s on amd64",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "S",
|
||||
Usage: "print assembly and machine code",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "trimpath",
|
||||
Usage: "remove prefix from recorded source file paths",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "shared",
|
||||
Usage: "generate code that can be linked into a shared library",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "dynlink",
|
||||
Usage: "support references to Go symbols defined in other shared libraries",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "D",
|
||||
Usage: "predefined symbol with optional simple value -D=identifer=value; can be set multiple times",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "I",
|
||||
Usage: "include directory; can be set multiple times",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
switch obj.Getwaarch() {
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "link: unknown architecture %q\n", obj.Getwaarch())
|
||||
os.Exit(2)
|
||||
case "386":
|
||||
x86.Main()
|
||||
case "amd64", "amd64p32":
|
||||
amd64.Main()
|
||||
case "arm":
|
||||
arm.Main()
|
||||
case "arm64":
|
||||
arm64.Main()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func Main() {
|
||||
func linkarchinit() {
|
||||
ld.Thestring = "amd64"
|
||||
ld.Thelinkarch = &ld.Linkamd64
|
||||
if obj.Getgoarch() == "amd64p32" {
|
||||
if obj.Getwaarch() == "amd64p32" {
|
||||
ld.Thelinkarch = &ld.Linkamd64p32
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ func Main() {
|
||||
}
|
||||
|
||||
func linkarchinit() {
|
||||
ld.Thestring = obj.Getgoarch()
|
||||
ld.Thestring = obj.Getwaarch()
|
||||
ld.Thelinkarch = &ld.Linkarm64
|
||||
|
||||
ld.Thearch.Thechar = thechar
|
||||
|
||||
@@ -290,7 +290,7 @@ const (
|
||||
|
||||
func (mode *BuildMode) Set(s string) error {
|
||||
goos := obj.Getgoos()
|
||||
goarch := obj.Getgoarch()
|
||||
goarch := obj.Getwaarch()
|
||||
badmode := func() error {
|
||||
return fmt.Errorf("buildmode %s not supported on %s/%s", s, goos, goarch)
|
||||
}
|
||||
@@ -1167,7 +1167,7 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
|
||||
}
|
||||
|
||||
// First, check that the basic goos, goarch, and version match.
|
||||
t := fmt.Sprintf("%s %s %s ", goos, obj.Getgoarch(), obj_Getgoversion)
|
||||
t := fmt.Sprintf("%s %s %s ", goos, obj.Getwaarch(), obj_Getgoversion)
|
||||
|
||||
line = strings.TrimRight(line, "\n")
|
||||
if !strings.HasPrefix(line[10:]+" ", t) && Debug['f'] == 0 {
|
||||
@@ -1387,9 +1387,9 @@ func ldshlibsyms(shlib string) {
|
||||
}
|
||||
|
||||
func mywhatsys() {
|
||||
goroot = obj.Getgoroot()
|
||||
goroot = obj.Getwaroot()
|
||||
goos = obj.Getgoos()
|
||||
goarch = obj.Getgoarch()
|
||||
goarch = obj.Getwaarch()
|
||||
|
||||
if !strings.HasPrefix(goarch, Thestring) {
|
||||
log.Fatalf("cannot use %cc with GOARCH=%s", Thearch.Thechar, goarch)
|
||||
|
||||
@@ -68,9 +68,9 @@ func linknew(arch *LinkArch) *Link {
|
||||
ctxt.Hash = make(map[symVer]*LSym)
|
||||
ctxt.Arch = arch
|
||||
ctxt.Version = obj.HistVersion
|
||||
ctxt.Goroot = obj.Getgoroot()
|
||||
ctxt.Goroot = obj.Getwaroot()
|
||||
|
||||
p := obj.Getgoarch()
|
||||
p := obj.Getwaarch()
|
||||
if p != arch.Name {
|
||||
log.Fatalf("invalid goarch %s (want %s)", p, arch.Name)
|
||||
}
|
||||
|
||||
@@ -473,8 +473,8 @@ type Link struct {
|
||||
Bso *Biobuf
|
||||
Pathname string
|
||||
Windows int32
|
||||
Goroot string
|
||||
Goroot_final string
|
||||
Waroot string
|
||||
Waroot_final string
|
||||
Enforce_data_order int32
|
||||
Hash map[SymVer]*LSym
|
||||
LineHist LineHist
|
||||
|
||||
@@ -29,8 +29,8 @@ type LineHist struct {
|
||||
Ranges []LineRange // ranges for lookup
|
||||
Dir string // directory to qualify relative paths
|
||||
TrimPathPrefix string // remove leading TrimPath from recorded file names
|
||||
GOROOT string // current GOROOT
|
||||
GOROOT_FINAL string // target GOROOT
|
||||
WAROOT string // current WAROOT
|
||||
WAROOT_FINAL string // target WAROOT
|
||||
}
|
||||
|
||||
// A LineStack is an entry in the recorded line history.
|
||||
@@ -81,8 +81,8 @@ func (h *LineHist) setFile(stk *LineStack, file string) {
|
||||
} else {
|
||||
abs = abs[len(h.TrimPathPrefix)+1:]
|
||||
}
|
||||
} else if h.GOROOT_FINAL != "" && h.GOROOT_FINAL != h.GOROOT && hasPathPrefix(abs, h.GOROOT) {
|
||||
abs = h.GOROOT_FINAL + abs[len(h.GOROOT):]
|
||||
} else if h.WAROOT_FINAL != "" && h.WAROOT_FINAL != h.WAROOT && hasPathPrefix(abs, h.WAROOT) {
|
||||
abs = h.WAROOT_FINAL + abs[len(h.WAROOT):]
|
||||
}
|
||||
if abs == "" {
|
||||
abs = "??"
|
||||
|
||||
@@ -81,8 +81,8 @@ func Linknew(arch *LinkArch) *Link {
|
||||
ctxt.Hash = make(map[SymVer]*LSym)
|
||||
ctxt.Arch = arch
|
||||
ctxt.Version = HistVersion
|
||||
ctxt.Goroot = Getgoroot()
|
||||
ctxt.Goroot_final = os.Getenv("GOROOT_FINAL")
|
||||
ctxt.Waroot = Getwaroot()
|
||||
ctxt.Waroot_final = os.Getenv("WAROOT_FINAL")
|
||||
if runtime.GOOS == "windows" {
|
||||
// TODO(rsc): Remove ctxt.Windows and let callers use runtime.GOOS.
|
||||
ctxt.Windows = 1
|
||||
@@ -96,8 +96,8 @@ func Linknew(arch *LinkArch) *Link {
|
||||
buf = filepath.ToSlash(buf)
|
||||
ctxt.Pathname = buf
|
||||
|
||||
ctxt.LineHist.GOROOT = ctxt.Goroot
|
||||
ctxt.LineHist.GOROOT_FINAL = ctxt.Goroot_final
|
||||
ctxt.LineHist.WAROOT = ctxt.Waroot
|
||||
ctxt.LineHist.WAROOT_FINAL = ctxt.Waroot_final
|
||||
ctxt.LineHist.Dir = ctxt.Pathname
|
||||
|
||||
ctxt.Headtype = headtype(Getgoos())
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -200,16 +201,16 @@ func envOr(key, value string) string {
|
||||
return value
|
||||
}
|
||||
|
||||
func Getgoroot() string {
|
||||
return envOr("GOROOT", "")
|
||||
func Getwaroot() string {
|
||||
return envOr("WAROOT", "")
|
||||
}
|
||||
|
||||
func Getgoarch() string {
|
||||
return envOr("GOARCH", "")
|
||||
func Getwaarch() string {
|
||||
return envOr("WAARCH", runtime.GOARCH)
|
||||
}
|
||||
|
||||
func Getgoos() string {
|
||||
return envOr("GOOS", "")
|
||||
return envOr("WAOS", runtime.GOOS)
|
||||
}
|
||||
|
||||
func Atoi(s string) int {
|
||||
|
||||
2
main.go
2
main.go
@@ -27,6 +27,7 @@ import (
|
||||
"wa-lang.org/wa/internal/app/applogo"
|
||||
"wa-lang.org/wa/internal/app/applsp"
|
||||
"wa-lang.org/wa/internal/app/appp9asm"
|
||||
"wa-lang.org/wa/internal/app/appp9link"
|
||||
"wa-lang.org/wa/internal/app/appplay"
|
||||
"wa-lang.org/wa/internal/app/apprun"
|
||||
"wa-lang.org/wa/internal/app/appssa"
|
||||
@@ -112,6 +113,7 @@ func main() {
|
||||
|
||||
// 待完善的子命令(隐藏)
|
||||
appp9asm.CmdP9Asm,
|
||||
appp9link.CmdP9Link,
|
||||
appgo2wa.CmdGo2wa,
|
||||
appcir.CmdCir,
|
||||
appdoc.CmdDoc,
|
||||
|
||||
14
tests/p9asm-go/main_windows_amd64.go
Normal file
14
tests/p9asm-go/main_windows_amd64.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2024 武汉凹语言科技有限公司
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var Name string
|
||||
|
||||
func main()
|
||||
|
||||
func println(s string) {
|
||||
fmt.Println(s)
|
||||
}
|
||||
16
tests/p9asm-go/main_windows_amd64.s
Normal file
16
tests/p9asm-go/main_windows_amd64.s
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2024 武汉凹语言科技有限公司
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
GLOBL ·Name(SB),NOPTR,$24
|
||||
|
||||
DATA ·Name+0(SB)/8,$·Name+16(SB)
|
||||
DATA ·Name+8(SB)/8,$6
|
||||
DATA ·Name+16(SB)/8,$"walang"
|
||||
|
||||
TEXT ·main(SB), $16-0
|
||||
MOVQ ·Name+0(SB), AX; MOVQ AX, 0(SP)
|
||||
MOVQ ·Name+8(SB), BX; MOVQ BX, 8(SP)
|
||||
CALL ·println(SB)
|
||||
RET
|
||||
9
tests/p9asm/Makefile
Normal file
9
tests/p9asm/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
WA:=go run ../../main.go
|
||||
|
||||
default:
|
||||
$(WA) p9asm -o hello.o hello_windows.s
|
||||
|
||||
link:
|
||||
$(WA) p9link -H windows -o hello.exe hello.o
|
||||
|
||||
clean:
|
||||
35
tests/p9asm/hello_windows.s
Normal file
35
tests/p9asm/hello_windows.s
Normal file
@@ -0,0 +1,35 @@
|
||||
// msg 长度
|
||||
#define msg_len 13
|
||||
|
||||
// 数据段
|
||||
DATA msg+0(SB)/13, $"Hello World!\n"
|
||||
GLOBL msg(SB), (RODATA), $13
|
||||
|
||||
// 用于接收写入长度
|
||||
DATA nw+0(SB)/8, $0
|
||||
GLOBL nw(SB), (NOPTR), $8
|
||||
|
||||
// 声明需要用到的外部符号(Windows API)
|
||||
GLOBL GetStdHandle(SB),DUPOK, $0
|
||||
GLOBL WriteConsoleA(SB),DUPOK, $0
|
||||
|
||||
// main.main
|
||||
TEXT main·main(SB),$0-0
|
||||
// 获取标准输出句柄(这里用 -11,即 STD_OUTPUT_HANDLE)
|
||||
MOVQ $-11, CX
|
||||
CALL GetStdHandle(SB)
|
||||
|
||||
// 返回值在 AX 中(句柄)
|
||||
|
||||
// 准备参数:句柄、字符串地址、长度、写入长度地址、保留
|
||||
MOVQ AX, CX // 第一个参数:句柄
|
||||
|
||||
LEAQ msg(SB), DX // 第二个参数:字符串地址
|
||||
MOVQ $msg_len, R8 // 第三个参数:长度
|
||||
LEAQ nw(SB), R9 // 第四个参数:写入长度地址
|
||||
|
||||
MOVQ $0, R10 // 第五个参数:保留
|
||||
|
||||
CALL WriteConsoleA(SB)
|
||||
|
||||
RET
|
||||
Reference in New Issue
Block a user