Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
86 changes: 86 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,89 @@ jobs:

- name: Build
run: go build -v ./...

llgo-test:
name: llgo-test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-2022
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.26.7'

- name: Check out LLGo
uses: actions/checkout@v4
with:
repository: xgo-dev/llgo
# Includes the merged stdcall support required by the direct Winsock
# declarations while keeping this library test independent of R9.
ref: 6fc2ef150f95d8b9331433f325fcb1b6ee5ad4e4
path: .llgo

- name: Set up LLGo dependencies
uses: ./.llgo/.github/actions/setup-deps
with:
llvm-version: '19'

- name: Build LLGo
if: runner.os != 'Windows'
working-directory: .llgo
run: go build -tags=dev -o "$RUNNER_TEMP/llgo" ./cmd/llgo

- name: Test LLGo native bindings
if: runner.os != 'Windows'
env:
LLGO_BUILD_CACHE: 'off'
LLGO_ROOT: ${{ github.workspace }}/.llgo
run: |
"$RUNNER_TEMP/llgo" test -count=1 -v ./c ./c/math/rand ./c/net ./c/os ./c/setjmp ./c/time ./cpp/std

# The Unix binding exposes libc++'s C++ ABI and is therefore exercised on
# macOS. Linux LLVM packages use libstdc++; Windows is tested below through
# its stable C bridge.
- name: Test LLGo LLVM demangle bindings
if: runner.os == 'macOS'
env:
LLGO_BUILD_CACHE: 'off'
LLGO_ROOT: ${{ github.workspace }}/.llgo
run: |
"$RUNNER_TEMP/llgo" test -v ./cpp/llvm

- name: Build LLGo on Windows
if: runner.os == 'Windows'
working-directory: .llgo
shell: pwsh
run: go build -tags=dev -o "$env:RUNNER_TEMP\llgo.exe" ./cmd/llgo

- name: Test LLGo Windows bindings
if: runner.os == 'Windows'
shell: pwsh
env:
LLGO_BUILD_CACHE: 'off'
LLGO_REQUIRE_MSVC: '1'
LLGO_ROOT: ${{ github.workspace }}/.llgo
run: |
$ErrorActionPreference = "Stop"
$llgo = Join-Path $env:RUNNER_TEMP "llgo.exe"

& $llgo test -count=1 -v `
./c `
./c/math/rand `
./c/net `
./c/os `
./c/setjmp `
./c/time `
./cpp/llvm `
./cpp/std
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
4 changes: 0 additions & 4 deletions c/c.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ import (
"unsafe"
)

const (
LLGoPackage = "decl"
)

type (
Void = [0]byte
Char = int8
Expand Down
23 changes: 0 additions & 23 deletions c/math/rand/rand.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,10 @@ import (
"github.com/goplus/lib/c"
)

const (
LLGoPackage = "decl"
)

// -----------------------------------------------------------------------------

//go:linkname Rand C.rand
func Rand() c.Int

//go:linkname RandR C.rand_r
func RandR(*c.Uint) c.Int

//go:linkname Srand C.srand
func Srand(c.Uint)

//go:linkname Sranddev C.sranddev
func Sranddev()

// -----------------------------------------------------------------------------

//go:linkname Random C.random
func Random() c.Long

//go:linkname Srandom C.srandom
func Srandom(c.Uint)

//go:linkname Srandomdev C.srandomdev
func Srandomdev()

// -----------------------------------------------------------------------------
28 changes: 28 additions & 0 deletions c/math/rand/rand_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//go:build !windows

// Copyright (c) 2026 The GoPlus Authors. Licensed under the Apache License 2.0.

package rand

import (
_ "unsafe"

"github.com/goplus/lib/c"
)

const LLGoPackage = "decl"

//go:linkname RandR C.rand_r
func RandR(*c.Uint) c.Int

//go:linkname Sranddev C.sranddev
func Sranddev()

//go:linkname Random C.random
func Random() c.Long

//go:linkname Srandom C.srandom
func Srandom(c.Uint)

//go:linkname Srandomdev C.srandomdev
func Srandomdev()
9 changes: 9 additions & 0 deletions c/math/rand/rand_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//go:build windows

// Copyright (c) 2026 The GoPlus Authors. Licensed under the Apache License 2.0.

package rand

// The Universal CRT provides only the ISO C rand and srand functions declared
// in rand.go. BSD/POSIX extensions remain in rand_default.go.
const LLGoPackage = "decl"
20 changes: 20 additions & 0 deletions c/math/rand/rand_windows_llgo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//go:build llgo && windows

// Copyright (c) 2026 The GoPlus Authors. Licensed under the Apache License 2.0.

package rand_test

import (
"testing"

"github.com/goplus/lib/c/math/rand"
)

func TestWindowsRand(t *testing.T) {
rand.Srand(1)
first := rand.Rand()
rand.Srand(1)
if got := rand.Rand(); got != first {
t.Fatalf("rand after equal seeds = %d, want %d", got, first)
}
}
20 changes: 20 additions & 0 deletions c/net/addrinfo_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//go:build windows

// Copyright (c) 2026 The GoPlus Authors. Licensed under the Apache License 2.0.

package net

import "github.com/goplus/lib/c"

// AddrInfo matches the Winsock ADDRINFOA layout. ai_addrlen is size_t on
// Windows, unlike the socklen_t field used by Unix implementations.
type AddrInfo struct {
Flags c.Int
Family c.Int
SockType c.Int
Protocol c.Int
AddrLen uintptr
CanOnName *c.Char
Addr *SockAddr
Next *AddrInfo
}
77 changes: 77 additions & 0 deletions c/net/functions_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//go:build windows

// Copyright (c) 2026 The GoPlus Authors. Licensed under the Apache License 2.0.

package net

import (
_ "unsafe"

"github.com/goplus/lib/c"
)

// Winsock uses stdcall on Windows/386. On Windows/AMD64 and Windows/ARM64,
// stdcall maps to the platform's unified native C calling convention.

//go:linkname WSAStartup stdcall.WSAStartup
func WSAStartup(version uint16, data *WSAData) c.Int

//go:linkname WSACleanup stdcall.WSACleanup
func WSACleanup() c.Int

//go:linkname Getaddrinfo stdcall.getaddrinfo
func Getaddrinfo(host *c.Char, port *c.Char, addrInfo *AddrInfo, result **AddrInfo) c.Int

//go:linkname Freeaddrinfo stdcall.freeaddrinfo
func Freeaddrinfo(addrInfo *AddrInfo)

//go:linkname Socket stdcall.socket
func Socket(domain c.Int, typ c.Int, protocol c.Int) SocketT

//go:linkname Bind stdcall.bind
func Bind(sockfd SocketT, addr *SockAddr, addrlen SocklenT) c.Int

//go:linkname Connect stdcall.connect
func Connect(sockfd SocketT, addr *SockAddr, addrlen SocklenT) c.Int

//go:linkname Listen stdcall.listen
func Listen(sockfd SocketT, backlog c.Int) c.Int

//go:linkname Accept stdcall.accept
func Accept(sockfd SocketT, addr *SockAddr, addrlen *SocklenT) SocketT

//go:linkname Closesocket stdcall.closesocket
func Closesocket(sockfd SocketT) c.Int

//go:linkname GetHostByName stdcall.gethostbyname
func GetHostByName(name *c.Char) *Hostent

//go:linkname InetNtop stdcall.inet_ntop
func InetNtop(af c.Int, src c.Pointer, dst *c.Char, size uintptr) *c.Char

//go:linkname InetAddr stdcall.inet_addr
func InetAddr(value *c.Char) c.Uint

//go:linkname Send stdcall.send
func Send(sockfd SocketT, buffer c.Pointer, length c.Int, flags c.Int) c.Int

//go:linkname Recv stdcall.recv
func Recv(sockfd SocketT, buffer c.Pointer, length c.Int, flags c.Int) c.Int

//go:linkname SetSockOpt stdcall.setsockopt
func SetSockOpt(sockfd SocketT, level c.Int, optionName c.Int, optionValue c.Pointer, optionLength SocklenT) c.Int

//go:linkname Ntohs stdcall.ntohs
func Ntohs(value uint16) uint16

//go:linkname Htons stdcall.htons
func Htons(value uint16) uint16

//go:linkname Ntohl stdcall.ntohl
func Ntohl(value c.Uint) c.Uint

//go:linkname Htonl stdcall.htonl
func Htonl(value c.Uint) c.Uint

//go:linkname WSAGetLastError stdcall.WSAGetLastError
func WSAGetLastError() c.Int
4 changes: 3 additions & 1 deletion c/net/net.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build !windows

/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
Expand Down Expand Up @@ -218,6 +220,6 @@ type AddrInfo struct {
func Getaddrinfo(host *c.Char, port *c.Char, addrInfo *AddrInfo, result **AddrInfo) c.Int

//go:linkname Freeaddrinfo C.freeaddrinfo
func Freeaddrinfo(addrInfo *AddrInfo) c.Int
func Freeaddrinfo(addrInfo *AddrInfo)

// -----------------------------------------------------------------------------
Loading
Loading