From e577b4074314c30bc967c5e03d1f3bc877d18339 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 15 Nov 2019 15:14:28 +0200 Subject: [PATCH] compiler: add support for $if x32, x64, big_endian, little_endian --- vlib/compiler/cheaders.v | 16 ++++++++ vlib/compiler/comptime.v | 19 ++++++--- .../comptime_bittness_and_endianess_test.v | 26 ++++++++++++ vlib/os/os.v | 6 +-- vlib/runtime/runtime.v | 40 ++++++++++++------- .../{runtime_lin.v => runtime_linux.v} | 0 vlib/runtime/runtime_nix.v | 16 ++++++++ vlib/runtime/runtime_test.v | 28 +++++++++++++ vlib/runtime/runtime_win.v | 15 +++++++ 9 files changed, 144 insertions(+), 22 deletions(-) create mode 100644 vlib/compiler/tests/comptime_bittness_and_endianess_test.v rename vlib/runtime/{runtime_lin.v => runtime_linux.v} (100%) create mode 100644 vlib/runtime/runtime_nix.v diff --git a/vlib/compiler/cheaders.v b/vlib/compiler/cheaders.v index dadfb149c8..e9da07254b 100644 --- a/vlib/compiler/cheaders.v +++ b/vlib/compiler/cheaders.v @@ -12,6 +12,22 @@ c_headers = ' #include // for va_list #include // 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 #include #include // tolower diff --git a/vlib/compiler/comptime.v b/vlib/compiler/comptime.v index 01c3c6ceb5..cb5dffb40e 100644 --- a/vlib/compiler/comptime.v +++ b/vlib/compiler/comptime.v @@ -62,18 +62,27 @@ fn (p mut Parser) comp_time() { 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' { - p.genln('#ifdef VDEBUG') - p.check(.lcbr) - p.statements_no_rcbr() - p.genln('#endif') + p.comptime_if_block('VDEBUG') } else if name == 'tinyc' { p.comptime_if_block('__TINYC__') } else if name == 'glibc' { p.comptime_if_block('__GLIBC__') - } + } else if name == 'mingw' { p.comptime_if_block('__MINGW32__') } diff --git a/vlib/compiler/tests/comptime_bittness_and_endianess_test.v b/vlib/compiler/tests/comptime_bittness_and_endianess_test.v new file mode 100644 index 0000000000..4b83af8415 --- /dev/null +++ b/vlib/compiler/tests/comptime_bittness_and_endianess_test.v @@ -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 +} diff --git a/vlib/os/os.v b/vlib/os/os.v index f9e0794fce..fe1f4ca11c 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -806,14 +806,14 @@ pub fn chdir(path string) { pub fn getwd() string { $if windows { max := 512 // MAX_PATH * sizeof(wchar_t) - buf := &u16(malloc(max*2)) + buf := &u16(calloc(max*2)) if C._wgetcwd(buf, max) == 0 { return '' } return string_from_wide(buf) } $else { - buf := malloc(512) + buf := calloc(512) if C.getcwd(buf, 512) == 0 { return '' } @@ -827,7 +827,7 @@ pub fn getwd() string { // and https://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html // NB: this particular rabbit hole is *deep* ... pub fn realpath(fpath string) string { - mut fullpath := malloc( MAX_PATH ) + mut fullpath := calloc( MAX_PATH ) mut res := 0 $if windows { res = int( C._fullpath( fullpath, fpath.str, MAX_PATH ) ) diff --git a/vlib/runtime/runtime.v b/vlib/runtime/runtime.v index cfede391c1..3296a40c75 100644 --- a/vlib/runtime/runtime.v +++ b/vlib/runtime/runtime.v @@ -4,8 +4,6 @@ module runtime -import os - //$if linux { fn C.sysconf(name int) i64 //} @@ -15,18 +13,32 @@ fn C.GetCurrentProcessorNumber() u32 //} 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 { - mut nr := int(C.GetCurrentProcessorNumber()) - if nr == 0 { - nr = os.getenv('NUMBER_OF_PROCESSORS').int() - } - return nr + return nr_cpus_win() } - return 1 + return nr_cpus_nix() +} + +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 } diff --git a/vlib/runtime/runtime_lin.v b/vlib/runtime/runtime_linux.v similarity index 100% rename from vlib/runtime/runtime_lin.v rename to vlib/runtime/runtime_linux.v diff --git a/vlib/runtime/runtime_nix.v b/vlib/runtime/runtime_nix.v new file mode 100644 index 0000000000..d57824b080 --- /dev/null +++ b/vlib/runtime/runtime_nix.v @@ -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 +} diff --git a/vlib/runtime/runtime_test.v b/vlib/runtime/runtime_test.v index 00d1bb72fa..5cab789536 100644 --- a/vlib/runtime/runtime_test.v +++ b/vlib/runtime/runtime_test.v @@ -4,3 +4,31 @@ fn test_nr_cpus() { nr_cpus := runtime.nr_cpus() 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() +} diff --git a/vlib/runtime/runtime_win.v b/vlib/runtime/runtime_win.v index 7777c00615..a084cda858 100644 --- a/vlib/runtime/runtime_win.v +++ b/vlib/runtime/runtime_win.v @@ -1 +1,16 @@ 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 +}