Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Windows: add i386 (windows/386) support #4629

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
windows: add windows/386 support
  • Loading branch information
aykevl committed Nov 22, 2024
commit e51941976cdb2f698af8df5b673560bf5dbf250d
1 change: 1 addition & 0 deletions builder/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func TestClangAttributes(t *testing.T) {
{GOOS: "linux", GOARCH: "mipsle", GOMIPS: "softfloat"},
{GOOS: "darwin", GOARCH: "amd64"},
{GOOS: "darwin", GOARCH: "arm64"},
{GOOS: "windows", GOARCH: "386"},
{GOOS: "windows", GOARCH: "amd64"},
{GOOS: "windows", GOARCH: "arm64"},
{GOOS: "wasip1", GOARCH: "wasm"},
Expand Down
3 changes: 3 additions & 0 deletions builder/mingw-w64.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ func makeMinGWExtraLibs(tmpdir, goarch string) []*compileJob {
defpath := inpath
var archDef, emulation string
switch goarch {
case "386":
archDef = "-DDEF_I386"
emulation = "i386pe"
case "amd64":
archDef = "-DDEF_X64"
emulation = "i386pep"
Expand Down
18 changes: 12 additions & 6 deletions compileopts/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,14 +420,20 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
case "windows":
spec.Linker = "ld.lld"
spec.Libc = "mingw-w64"
// Note: using a medium code model, low image base and no ASLR
// because Go doesn't really need those features. ASLR patches
// around issues for unsafe languages like C/C++ that are not
// normally present in Go (without explicitly opting in).
// For more discussion:
// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1
switch options.GOARCH {
case "386":
spec.LDFlags = append(spec.LDFlags,
"-m", "i386pe",
)
// __udivdi3 is not present in ucrt it seems.
spec.RTLib = "compiler-rt"
case "amd64":
// Note: using a medium code model, low image base and no ASLR
// because Go doesn't really need those features. ASLR patches
// around issues for unsafe languages like C/C++ that are not
// normally present in Go (without explicitly opting in).
// For more discussion:
// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1
spec.LDFlags = append(spec.LDFlags,
"-m", "i386pep",
"--image-base", "0x400000",
Expand Down
7 changes: 7 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ func TestBuild(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("wasip2", sema), tests, t)
})
} else if runtime.GOOS == "windows" {
if runtime.GOARCH != "386" {
t.Run("Windows386", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromOSARCH("windows/386", sema), tests, t)
})
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/internal/task/task_stack_386.S
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#ifdef _WIN32
.global _tinygo_startTask
_tinygo_startTask:
#else // Linux etc
.section .text.tinygo_startTask
.global tinygo_startTask
.type tinygo_startTask, %function
tinygo_startTask:
#endif
.cfi_startproc
// Small assembly stub for starting a goroutine. This is already run on the
// new stack, with the callee-saved registers already loaded.
Expand All @@ -24,12 +29,21 @@ tinygo_startTask:
addl $4, %esp

// After return, exit this goroutine. This is a tail call.
#ifdef _WIN32
jmp _tinygo_pause
#else
jmp tinygo_pause
#endif
.cfi_endproc

#ifdef _WIN32
.global _tinygo_swapTask
_tinygo_swapTask:
#else
.global tinygo_swapTask
.type tinygo_swapTask, %function
tinygo_swapTask:
#endif
// This function gets the following parameters:
movl 4(%esp), %eax // newStack uintptr
movl 8(%esp), %ecx // oldStack *uintptr
Expand Down
14 changes: 14 additions & 0 deletions src/runtime/asm_386.S
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#ifdef _WIN32
.global _tinygo_scanCurrentStack
_tinygo_scanCurrentStack:
#else
.section .text.tinygo_scanCurrentStack
.global tinygo_scanCurrentStack
.type tinygo_scanCurrentStack, %function
tinygo_scanCurrentStack:
#endif
// Sources:
// * https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call
// * https://godbolt.org/z/q7e8dn
Expand All @@ -15,17 +20,26 @@ tinygo_scanCurrentStack:
// Scan the stack.
subl $8, %esp // adjust the stack before the call to maintain 16-byte alignment
pushl %esp
#ifdef _WIN32
calll _tinygo_scanstack
#else
calll tinygo_scanstack
#endif

// Restore the stack pointer. Registers do not need to be restored as they
// were only pushed to be discoverable by the GC.
addl $28, %esp
retl


#ifdef _WIN32
.global _tinygo_longjmp
_tinygo_longjmp:
#else
.section .text.tinygo_longjmp
.global tinygo_longjmp
tinygo_longjmp:
#endif
// Note: the code we jump to assumes eax is set to a non-zero value if we
// jump from here.
movl 4(%esp), %eax
Expand Down
Loading