Widen `ecall` intrinsic args

3ca028fc0bb8eda3776bcdddb4fd85f1de91d1fd96925b3facc73105def15f00
Change the ecall intrinsic signature and all call sites from `i32` to `i64`
arguments and return value.
Alexis Sellier committed ago 1 parent a0bdac6c
lib/std/intrinsics.rad +5 -1
1 1
//! Compiler intrinsics.
2 2
3 3
/// Environment call.
4 -
@intrinsic pub extern fn ecall(number: u32, arg1: i32, arg2: i32, arg3: i32, arg4: i32) -> i32;
4 +
///
5 +
/// Issues a system call with the given number and arguments.
6 +
/// Arguments and the return value are `i64` to support both 32-bit
7 +
/// emulator addresses and 64-bit native (AMD64) pointers.
8 +
@intrinsic pub extern fn ecall(number: u32, arg1: i64, arg2: i64, arg3: i64, arg4: i64) -> i64;
5 9
6 10
/// Break out of program.
7 11
@intrinsic pub extern fn ebreak();
lib/std/io.rad +3 -3
1 1
//! Input/output utilities.
2 2
use std::fmt;
3 3
use std::intrinsics;
4 4
5 5
pub fn print(str: *[u8]) {
6 -
    intrinsics::ecall(64, 1, str.ptr as i32, str.len as i32, 0);
6 +
    intrinsics::ecall(64, 1, str.ptr as i64, str.len as i64, 0);
7 7
}
8 8
9 9
pub fn printError(str: *[u8]) {
10 -
    intrinsics::ecall(64, 2, str.ptr as i32, str.len as i32, 0);
10 +
    intrinsics::ecall(64, 2, str.ptr as i64, str.len as i64, 0);
11 11
}
12 12
13 13
pub fn printLn(str: *[u8]) {
14 14
    print(str);
15 15
    print("\n");
32 32
    let result: *[u8] = fmt::formatBool(val, &mut buffer[..]);
33 33
    print(result);
34 34
}
35 35
36 36
pub fn read(buf: *mut [u8]) -> u32 {
37 -
    return intrinsics::ecall(63, 0, buf.ptr as i32, buf.len as i32, 0) as u32;
37 +
    return intrinsics::ecall(63, 0, buf.ptr as i64, buf.len as i64, 0) as u32;
38 38
}
39 39
40 40
pub fn readToEnd(buf: *mut [u8]) -> *[u8] {
41 41
    let mut total: u32 = 0;
42 42
lib/std/sys/unix.rad +17 -17
2 2
use std::intrinsics;
3 3
4 4
/// File access modes.
5 5
// TODO: Use unlabeled struct.
6 6
pub record OpenFlags {
7 -
    value: i32,
7 +
    value: i64,
8 8
}
9 9
10 10
/// Open file for reading only.
11 11
pub const O_RDONLY: OpenFlags = OpenFlags { value: 0 };
12 12
21 21
22 22
/// Truncate file to zero length.
23 23
pub const O_TRUNC: OpenFlags = OpenFlags { value: 512 };
24 24
25 25
/// Standard file descriptor for stdin.
26 -
pub const STDIN: i32 = 0;
26 +
pub const STDIN: i64 = 0;
27 27
28 28
/// Standard file descriptor for stdout.
29 -
pub const STDOUT: i32 = 1;
29 +
pub const STDOUT: i64 = 1;
30 30
31 31
/// Standard file descriptor for stderr.
32 -
pub const STDERR: i32 = 2;
32 +
pub const STDERR: i64 = 2;
33 33
34 34
/// Special value representing current working directory for `openat()`.
35 -
const AT_FDCWD: i32 = -100;
35 +
const AT_FDCWD: i64 = -100;
36 36
37 37
/// Opens a file at the given path and returns a file descriptor.
38 38
/// Returns a negative value on error.
39 -
pub fn open(path: *[u8], flags: OpenFlags) -> i32 {
40 -
    return intrinsics::ecall(56, AT_FDCWD, path.ptr as i32, flags.value, 0);
39 +
pub fn open(path: *[u8], flags: OpenFlags) -> i64 {
40 +
    return intrinsics::ecall(56, AT_FDCWD, path.ptr as i64, flags.value, 0);
41 41
}
42 42
43 43
/// Opens a file at the given path with mode, returns a file descriptor.
44 -
pub fn openOpts(path: *[u8], flags: OpenFlags, mode: i32) -> i32 {
45 -
    return intrinsics::ecall(56, AT_FDCWD, path.ptr as i32, flags.value, mode);
44 +
pub fn openOpts(path: *[u8], flags: OpenFlags, mode: i64) -> i64 {
45 +
    return intrinsics::ecall(56, AT_FDCWD, path.ptr as i64, flags.value, mode);
46 46
}
47 47
48 48
/// Reads from a file descriptor into the provided buffer.
49 49
/// Returns the number of bytes read, or a negative value on error.
50 -
pub fn read(fd: i32, buf: *mut [u8]) -> i32 {
51 -
    return intrinsics::ecall(63, fd, buf.ptr as i32, buf.len as i32, 0);
50 +
pub fn read(fd: i64, buf: *mut [u8]) -> i64 {
51 +
    return intrinsics::ecall(63, fd, buf.ptr as i64, buf.len as i64, 0);
52 52
}
53 53
54 54
/// Reads from a file descriptor until EOF or buffer is full.
55 55
/// Returns the total number of bytes read, or a negative value on error.
56 -
pub fn readToEnd(fd: i32, buf: *mut [u8]) -> i32 {
56 +
pub fn readToEnd(fd: i64, buf: *mut [u8]) -> i64 {
57 57
    let mut total: u32 = 0;
58 58
    while total < buf.len {
59 59
        let chunk = &mut buf[total..];
60 60
        let n = read(fd, chunk);
61 61
65 65
        if n == 0 {
66 66
            break;
67 67
        }
68 68
        total += n as u32;
69 69
    }
70 -
    return total as i32;
70 +
    return total as i64;
71 71
}
72 72
73 73
/// Writes to a file descriptor from the provided buffer.
74 74
/// Returns the number of bytes written, or a negative value on error.
75 -
pub fn write(fd: i32, buf: *[u8]) -> i32 {
76 -
    return intrinsics::ecall(64, fd, buf.ptr as i32, buf.len as i32, 0);
75 +
pub fn write(fd: i64, buf: *[u8]) -> i64 {
76 +
    return intrinsics::ecall(64, fd, buf.ptr as i64, buf.len as i64, 0);
77 77
}
78 78
79 79
/// Closes a file descriptor.
80 80
/// Returns `0` on success, or a negative value on error.
81 -
pub fn close(fd: i32) -> i32 {
81 +
pub fn close(fd: i64) -> i64 {
82 82
    return intrinsics::ecall(57, fd, 0, 0, 0);
83 83
}
84 84
85 85
86 86
/// Reads the entire contents of a file at the given path into the provided buffer.
100 100
    }
101 101
    return &buf[..(n as u32)];
102 102
}
103 103
104 104
/// Exit the current process with the given status code.
105 -
pub fn exit(status: i32) {
105 +
pub fn exit(status: i64) {
106 106
    intrinsics::ecall(93, status, 0, 0, 0);
107 107
}
108 108
109 109
/// Writes the entire contents of a buffer to a file at the given path.
110 110
/// Creates the file if it doesn't exist, truncates if it does.
test/tests/ecall.i64.rad added +18 -0
1 +
//! returns: 0
2 +
3 +
@intrinsic extern fn ecall(number: u32, arg1: i64, arg2: i64, arg3: i64, arg4: i64) -> i64;
4 +
5 +
/// Test that ecall can pass and return i64 values.
6 +
@default fn main() -> i32 {
7 +
    // ecall(64, fd, buf, len, 0) = write(fd, buf, len).
8 +
    let msg: *[u8] = "ok\n";
9 +
10 +
    // Write to stdout. The pointer is passed as i64.
11 +
    let n = ecall(64, 1, msg.ptr as i64, msg.len as i64, 0);
12 +
13 +
    // Return value should be 3 (bytes written).
14 +
    if n != 3 {
15 +
        return 1;
16 +
    }
17 +
    return 0;
18 +
}