compiler: add support for $if x32, x64, big_endian, little_endian

pull/2773/head
Delyan Angelov 2019-11-15 15:14:28 +02:00 committed by Alexander Medvednikov
parent 751a89ccc8
commit e577b40743
9 changed files with 144 additions and 22 deletions

View File

@ -12,6 +12,22 @@ c_headers = '
#include <stdarg.h> // for va_list #include <stdarg.h> // for va_list
#include <string.h> // memcpy #include <string.h> // memcpy
#if INTPTR_MAX == INT32_MAX
#define TARGET_IS_32BIT 1
#elif INTPTR_MAX == INT64_MAX
#define TARGET_IS_64BIT 1
#else
#error "The environment is not 32 or 64-bit."
#endif
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
#define TARGET_ORDER_IS_BIG
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86)
#define TARGET_ORDER_IS_LITTLE
#else
#error "Unknown architecture endianness"
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <ctype.h> #include <ctype.h>
#include <locale.h> // tolower #include <locale.h> // tolower

View File

@ -62,11 +62,20 @@ fn (p mut Parser) comp_time() {
p.genln('#endif') p.genln('#endif')
} }
} }
else if name == 'x64' {
p.comptime_if_block('TARGET_IS_64BIT')
}
else if name == 'x32' {
p.comptime_if_block('TARGET_IS_32BIT')
}
else if name == 'big_endian' {
p.comptime_if_block('TARGET_ORDER_IS_BIG')
}
else if name == 'little_endian' {
p.comptime_if_block('TARGET_ORDER_IS_LITTLE')
}
else if name == 'debug' { else if name == 'debug' {
p.genln('#ifdef VDEBUG') p.comptime_if_block('VDEBUG')
p.check(.lcbr)
p.statements_no_rcbr()
p.genln('#endif')
} }
else if name == 'tinyc' { else if name == 'tinyc' {
p.comptime_if_block('__TINYC__') p.comptime_if_block('__TINYC__')

View File

@ -0,0 +1,26 @@
fn test_bitness(){
mut x := 0
$if x32 {
println('system is 32 bit')
x = 1
}
$if x64 {
println('system is 64 bit')
x = 2
}
assert x > 0
}
fn test_endianness(){
mut x := 0
$if little_endian {
println('system is little endian')
x = 1
}
$if big_endian {
println('system is big endian')
x = 2
}
assert x > 0
}

View File

@ -806,14 +806,14 @@ pub fn chdir(path string) {
pub fn getwd() string { pub fn getwd() string {
$if windows { $if windows {
max := 512 // MAX_PATH * sizeof(wchar_t) max := 512 // MAX_PATH * sizeof(wchar_t)
buf := &u16(malloc(max*2)) buf := &u16(calloc(max*2))
if C._wgetcwd(buf, max) == 0 { if C._wgetcwd(buf, max) == 0 {
return '' return ''
} }
return string_from_wide(buf) return string_from_wide(buf)
} }
$else { $else {
buf := malloc(512) buf := calloc(512)
if C.getcwd(buf, 512) == 0 { if C.getcwd(buf, 512) == 0 {
return '' return ''
} }
@ -827,7 +827,7 @@ pub fn getwd() string {
// and https://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html // and https://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html
// NB: this particular rabbit hole is *deep* ... // NB: this particular rabbit hole is *deep* ...
pub fn realpath(fpath string) string { pub fn realpath(fpath string) string {
mut fullpath := malloc( MAX_PATH ) mut fullpath := calloc( MAX_PATH )
mut res := 0 mut res := 0
$if windows { $if windows {
res = int( C._fullpath( fullpath, fpath.str, MAX_PATH ) ) res = int( C._fullpath( fullpath, fpath.str, MAX_PATH ) )

View File

@ -4,8 +4,6 @@
module runtime module runtime
import os
//$if linux { //$if linux {
fn C.sysconf(name int) i64 fn C.sysconf(name int) i64
//} //}
@ -15,18 +13,32 @@ fn C.GetCurrentProcessorNumber() u32
//} //}
pub fn nr_cpus() int { pub fn nr_cpus() int {
$if linux {
return int(C.sysconf(C._SC_NPROCESSORS_ONLN))
}
$if mac {
return int(C.sysconf(C._SC_NPROCESSORS_ONLN))
}
$if windows { $if windows {
mut nr := int(C.GetCurrentProcessorNumber()) return nr_cpus_win()
if nr == 0 {
nr = os.getenv('NUMBER_OF_PROCESSORS').int()
} }
return nr return nr_cpus_nix()
} }
return 1
pub fn is_32bit() bool {
mut x := false
$if x32 { x = true }
return x
}
pub fn is_64bit() bool {
mut x := false
$if x64 { x = true }
return x
}
pub fn is_little_endian() bool {
mut x := false
$if little_endian { x = true }
return x
}
pub fn is_big_endian() bool {
mut x := false
$if big_endian { x = true }
return x
} }

View File

@ -0,0 +1,16 @@
module runtime
fn nr_cpus_nix() int {
$if linux {
return int(C.sysconf(C._SC_NPROCESSORS_ONLN))
}
$if mac {
return int(C.sysconf(C._SC_NPROCESSORS_ONLN))
}
return 1
}
fn nr_cpus_win() int {
eprintln('nr_cpus_win should be callable only for windows')
return 1
}

View File

@ -4,3 +4,31 @@ fn test_nr_cpus() {
nr_cpus := runtime.nr_cpus() nr_cpus := runtime.nr_cpus()
assert nr_cpus > 0 assert nr_cpus > 0
} }
fn test_is_32bit(){
x := runtime.is_32bit().str()
assert x == 'true' || x == 'false'
}
fn test_is_64bit(){
x := runtime.is_64bit().str()
assert x == 'true' || x == 'false'
}
fn test_is_little_endian(){
x := runtime.is_little_endian().str()
assert x == 'true' || x == 'false'
}
fn test_is_big_endian(){
x := runtime.is_big_endian().str()
assert x == 'true' || x == 'false'
}
fn test_is_big_endian_different_than_is_little_endian(){
assert runtime.is_big_endian() != runtime.is_little_endian()
}
fn test_is_32bit_different_than_is_64bit(){
assert runtime.is_32bit() != runtime.is_64bit()
}

View File

@ -1 +1,16 @@
module runtime module runtime
import os
fn nr_cpus_win() int {
mut nr := int(C.GetCurrentProcessorNumber())
if nr == 0 {
nr = os.getenv('NUMBER_OF_PROCESSORS').int()
}
return nr
}
fn nr_cpus_nix() int {
eprintln('nr_cpus_nix should be callable only for nix platforms')
return 1
}