完善 p9asm

This commit is contained in:
chai2010
2025-07-15 15:20:39 +08:00
parent 445a77d72a
commit 8576f34117
16 changed files with 205 additions and 28 deletions

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ wa.exe
*.exe
*.dll
*.a
*.o
*.so
*.dylib
*.out*

View File

@@ -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
},
}

View 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
},
}

View File

@@ -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
}

View File

@@ -46,7 +46,7 @@ func Main() {
}
func linkarchinit() {
ld.Thestring = obj.Getgoarch()
ld.Thestring = obj.Getwaarch()
ld.Thelinkarch = &ld.Linkarm64
ld.Thearch.Thechar = thechar

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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 = "??"

View File

@@ -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())

View File

@@ -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 {

View File

@@ -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,

View 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)
}

View 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
View 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:

View 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