Skip to content

Commit

Permalink
add support for linux_riscv64 and freestanding_riscv64
Browse files Browse the repository at this point in the history
  • Loading branch information
laytan committed Aug 16, 2024
1 parent 14e2070 commit 6b85869
Show file tree
Hide file tree
Showing 28 changed files with 1,395 additions and 116 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,53 @@ jobs:
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style -target:windows_i386
build_linux_riscv64:
runs-on: ubuntu-latest
name: Linux riscv64 (emulated) Build, Check and Test
timeout-minutes: 15
steps:
- uses: actions/checkout@v4

- name: Download LLVM (Linux)
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 18
echo "/usr/lib/llvm-18/bin" >> $GITHUB_PATH
- name: Build Odin
run: ./build_odin.sh release

- name: Odin version
run: ./odin version

- name: Odin report
run: ./odin report

- name: Compile needed Vendor
run: |
make -C vendor/stb/src
make -C vendor/cgltf/src
make -C vendor/miniaudio/src
- name: Odin check
run: ./odin check examples/all -target:linux_riscv64 -vet -strict-style -disallow-do

- name: Install riscv64 toolchain and qemu
run: sudo apt-get install -y qemu-user qemu-user-static gcc-12-riscv64-linux-gnu libc6-riscv64-cross

- name: Odin run
run: ./odin run examples/demo -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"

- name: Odin run -debug
run: ./odin run examples/demo -debug -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"

- name: Normal Core library tests
run: ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"

- name: Optimized Core library tests
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"

- name: Internals tests
run: ./odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
3 changes: 3 additions & 0 deletions base/runtime/entry_unix.odin
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ when ODIN_BUILD_MODE == .Dynamic {
} else when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 {
@require foreign import entry "entry_unix_no_crt_darwin_arm64.asm"
SYS_exit :: 1
} else when ODIN_ARCH == .riscv64 {
@require foreign import entry "entry_unix_no_crt_riscv64.asm"
SYS_exit :: 93
}
@(link_name="_start_odin", linkage="strong", require)
_start_odin :: proc "c" (argc: i32, argv: [^]cstring) -> ! {
Expand Down
10 changes: 10 additions & 0 deletions base/runtime/entry_unix_no_crt_riscv64.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.text

.globl _start

_start:
ld a0, 0(sp)
addi a1, sp, 8
addi sp, sp, ~15
call _start_odin
ebreak
2 changes: 2 additions & 0 deletions base/runtime/os_specific_linux.odin
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
SYS_write :: uintptr(4)
} else when ODIN_ARCH == .arm32 {
SYS_write :: uintptr(4)
} else when ODIN_ARCH == .riscv64 {
SYS_write :: uintptr(64)
}

stderr :: 2
Expand Down
2 changes: 1 addition & 1 deletion core/crypto/_chacha20/simd128/chacha20_simd128.odin
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package chacha20_simd128
import "base:intrinsics"
import "core:crypto/_chacha20"
import "core:simd"
import "core:sys/info"
@(require) import "core:sys/info"

// Portable 128-bit `core:simd` implementation.
//
Expand Down
4 changes: 2 additions & 2 deletions core/net/socket_linux.odin
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Socket_Option :: enum c.int {
Linger = c.int(linux.Socket_Option.LINGER),
Receive_Buffer_Size = c.int(linux.Socket_Option.RCVBUF),
Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF),
Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO_NEW),
Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO_NEW),
Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO),
Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO),
}

// Wrappers and unwrappers for system-native types
Expand Down
19 changes: 19 additions & 0 deletions core/os/os_linux.odin
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,25 @@ when ODIN_ARCH == .arm64 {
_reserved: [2]i32,
}
#assert(size_of(OS_Stat) == 128)
} else when ODIN_ARCH == .riscv64 {
OS_Stat :: struct {
device_id: u64,
serial: u64,
mode: u32,
nlink: u32,
uid: u32,
gid: u32,
rdev: u64,
_: u64,
size: i64,
block_size: i32,
_: i32,
blocks: i64,
last_access: Unix_File_Time,
modified: Unix_File_Time,
status_change: Unix_File_Time,
_: [3]uint,
}
} else {
OS_Stat :: struct {
device_id: u64, // ID of device containing file
Expand Down
46 changes: 46 additions & 0 deletions core/sys/info/cpu_linux_riscv64.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//+build riscv64
//+build linux
package sysinfo

import "base:intrinsics"

import "core:sys/linux"

@(init, private)
init_cpu_features :: proc() {
fd, err := linux.open("/proc/self/auxv", {})
if err != .NONE { return }
defer linux.close(fd)

// This is probably enough right?
buf: [4096]byte
n, rerr := linux.read(fd, buf[:])
if rerr != .NONE || n == 0 { return }

ulong :: u64
AT_HWCAP :: 16

// TODO: using these we could get more information than just the basics.
// AT_HWCAP2 :: 26
// AT_HWCAP3 :: 29
// AT_HWCAP4 :: 30

auxv := buf[:n]
for len(auxv) >= size_of(ulong)*2 {
key := intrinsics.unaligned_load((^ulong)(&auxv[0]))
val := intrinsics.unaligned_load((^ulong)(&auxv[size_of(ulong)]))
auxv = auxv[2*size_of(ulong):]

if key != AT_HWCAP {
continue
}

cpu_features = transmute(CPU_Features)(val)
break
}
}

@(init, private)
init_cpu_name :: proc() {
cpu_name = "RISCV64"
}
16 changes: 16 additions & 0 deletions core/sys/info/cpu_riscv64.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package sysinfo

CPU_Feature :: enum u64 {
I = 'I' - 'A', // Base features, don't think this is ever not here.
M = 'M' - 'A', // Integer multiplication and division, currently required by Odin.
A = 'A' - 'A', // Atomics.
F = 'F' - 'A', // Single precision floating point, currently required by Odin.
D = 'D' - 'A', // Double precision floating point, currently required by Odin.
C = 'C' - 'A', // Compressed instructions.
V = 'V' - 'A', // Vector operations.
}

CPU_Features :: distinct bit_set[CPU_Feature; u64]

cpu_features: Maybe(CPU_Features)
cpu_name: Maybe(string)
2 changes: 1 addition & 1 deletion core/sys/info/sysinfo.odin
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package sysinfo

when !(ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64) {
when !(ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64) {
#assert(false, "This package is unsupported on this architecture.")
}

Expand Down
14 changes: 8 additions & 6 deletions core/sys/linux/bits.odin
Original file line number Diff line number Diff line change
Expand Up @@ -1343,14 +1343,16 @@ Socket_Option :: enum {
RESERVE_MEM = 73,
TXREHASH = 74,
RCVMARK = 75,
// Hardcoded 64-bit Time. It's time to move on.
TIMESTAMP = TIMESTAMP_NEW,
TIMESTAMPNS = TIMESTAMPNS_NEW,
TIMESTAMPING = TIMESTAMPING_NEW,
RCVTIMEO = RCVTIMEO_NEW,
SNDTIMEO = SNDTIMEO_NEW,
TIMESTAMP = TIMESTAMP_OLD when _SOCKET_OPTION_OLD else TIMESTAMP_NEW,
TIMESTAMPNS = TIMESTAMPNS_OLD when _SOCKET_OPTION_OLD else TIMESTAMPNS_NEW,
TIMESTAMPING = TIMESTAMPING_OLD when _SOCKET_OPTION_OLD else TIMESTAMPING_NEW,
RCVTIMEO = RCVTIMEO_OLD when _SOCKET_OPTION_OLD else RCVTIMEO_NEW,
SNDTIMEO = SNDTIMEO_OLD when _SOCKET_OPTION_OLD else SNDTIMEO_NEW,
}

@(private)
_SOCKET_OPTION_OLD :: size_of(rawptr) == 8 /* || size_of(time_t) == size_of(__kernel_long_t) */

Socket_UDP_Option :: enum {
CORK = 1,
ENCAP = 100,
Expand Down
Loading

0 comments on commit 6b85869

Please sign in to comment.