vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.67k stars 2.15k forks source link

C code compiling error #21939

Open baiango opened 1 month ago

baiango commented 1 month ago

Describe the bug

TCC and GCC on Windows failed to compile the C code. It can be done by v -o main.c main.v ; if ($?) { C:\tcc\tcc.exe main.c } in PowerShell with this code too, and get the error message main.c:414: error: include file 'stdnoreturn.h' not found.

fn is_prime(x int) bool {
    for i in 2..x / 2 + 1 {
        if x % i == 0 {
            return false
        }
    }
    return true
}

for i in 2..100 {
    if is_prime(i) {
        println('${i}')
    }
}

In V generated main.c code from 412 to 425 shows that it includes something with predetermined directories without my source codes:

#if !defined(VNORETURN)
    #if defined(__TINYC__)
        #include <stdnoreturn.h>
        #define VNORETURN noreturn
    #endif
    # if !defined(__TINYC__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
    #  define VNORETURN _Noreturn
    # elif !defined(VNORETURN) && defined(__GNUC__) && __GNUC__ >= 2
    #  define VNORETURN __attribute__((noreturn))
    # endif
    #ifndef VNORETURN
        #define VNORETURN
    #endif
#endif

Reproduction Steps

main.v

#flag -I @VMODROOT
#include "strcmp.h"

@[export: "is_prime"]
fn is_prime(x int) bool {
    for i in 2..x / 2 + 1 {
        if x % i == 0 {
            return false
        }
    }
    return true
}

for i in 2..100 {
    if is_prime(i) {
        println('${i}')
    }
}

strcmp.h

bool compare_ymm(__m256i *a, __m256i *b);

strcmp.c

#include "strcmp.h"
#include <immintrin.h>
#include <stdbool.h>

bool compare_ymm(__m256i *a, __m256i *b) {
    __m256i result = _mm256_xor_si256(*a, *b);
    int mask = _mm256_testz_si256(result, result);
    return mask != 0;
}

v.mod

Module {
    name: 'project_with_c_code',
    description: 'A simple project, containing C code.',
    dependencies: []
}

Expected Behavior

Compiles successful without an error and output.

Current Behavior

#flag -I @VMODROOT
#include "strcmp.h"

@[export: "is_prime"]
fn is_prime(x int) bool {
    for i in 2..x / 2 + 1 {
        if x % i == 0 {
            return false
        }
    }
    return true
}

for i in 2..100 {
    if is_prime(i) {
        println('${i}')
    }
}

v run "d:\unordered_map\main.v"

================== C compilation error (from tcc): ==============
cc: In file included from C:/Users/Administrator/AppData/Local/Temp/v_0/main.01J3S1FTG80Z8S1MDJXNTFYC2E.tmp.c:782:      
cc: D:/unordered_map/strcmp.h:1: error: ',' expected (got "*")
... (the original output was 3 lines long, and was truncated to 2 lines)
=================================================================
(You can pass `-cg`, or `-show-c-output` as well, to print all the C error messages).
builder error:
==================
C error found. It should never happen, when compiling pure V code.
This is a V compiler bug, please report it using `v bug file.v`,
or goto https://github.com/vlang/v/issues/new/choose .
You can also use #help on Discord: https://discord.gg/vlang .

Possible Solution

I do not know. I tried to inline the code, and it reports it does not support ymm0 register.

main.v

fn is_m256i_same_ptest(rdi voidptr, rsi voidptr) bool {
    mut result := false
    asm amd64 {
        vmovdqa ymm0, rdi
        vpxor   ymm0, ymm0, rsi
        vptest  ymm0, ymm0
        sete    al
        vzeroupper
        ; =r (result)
        ; r (rdi)
          r (rsi)
    }
    return result
}
PS D:\unordered_map> v run "d:\unordered_map\main.v"
================== C compilation error (from tcc): ==============
cc: C:/Users/Administrator/AppData/Local/Temp/v_0/main.01J3S24CKGK496HSPMB7B7D66J.tmp.c:6960: warning: implicit declaration of function 'tcc_backtrace'
cc: C:/Users/Administrator/AppData/Local/Temp/v_0/main.01J3S24CKGK496HSPMB7B7D66J.tmp.c:13374: error: unknown register %ymm0
... (the original output was 3 lines long, and was truncated to 2 lines)
=================================================================
(You can pass `-cg`, or `-show-c-output` as well, to print all the C error messages).
builder error:
==================
C error found. It should never happen, when compiling pure V code.
This is a V compiler bug, please report it using `v bug file.v`,
or goto https://github.com/vlang/v/issues/new/choose .
You can also use #help on Discord: https://discord.gg/vlang .

Additional Information/Context

======== Output of the C Compiler (C:\v\thirdparty\tcc\tcc.exe) ========                                                       _proc'       
C:/Users/Administrator/AppData/Local/Temp/v_0/main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:521: warning: WINVER redefined             : C:\Users\AD
In file included from C:/Users/Administrator/AppData/Local/Temp/v_0/main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:782:                 s_executable'
C:/Users/Administrator/source/repos/NOSMap/strcmp.h:1: error: ',' expected (got "*")                                           : C:\Users\AD
========================================================================
======== Output of the C Compiler (gcc) ========
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x123f5): undefined reference to `GC_malloc'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x1256b): undefined reference to `GC_malloc_atomic'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x126fd): undefined reference to `GC_malloc_uncollectable'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x127da): undefined reference to `GC_realloc'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x128b9): undefined reference to `GC_realloc'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x12a96): undefined reference to `GC_malloc'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x12b5d): undefined reference to `GC_malloc_atomic'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x12ce8): undefined reference to `GC_get_heap_usage_safe'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x12d2e): undefined reference to `GC_get_memory_use'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x137e8): undefined reference to `GC_is_disabled'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x13800): undefined reference to `GC_gcollect'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x13814): undefined reference to `GC_enable'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x13828): undefined reference to `GC_disable'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x13843): undefined reference to `GC_get_warn_proc'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x13861): undefined reference to `GC_set_warn_proc'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x28814): undefined reference to `GC_set_pages_executable'
C:/Users/Administrator/scoop/apps/gcc/13.2.0/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ADMINI~1\AppData\Local\Temp\ccFWzVeR.o:main.01J3RZV9F31GMY52Y1K88GKPF2.tmp.c:(.text+0x28819): undefined reference to `GC_init'
collect2.exe: error: ld returned 1 exit status
================================================
failed CreateProcess: The system cannot find the file specified.

V version

Current V version: V 0.4.7 52fe7c0, timestamp: 2024-07-26 10:28:17 +0300

Environment details (OS name and version, etc.)

V full version: V 0.4.7 52fe7c0
OS: windows, Microsoft Windows 10 Pro v19044 64-bit
Processor: 8 cpus, 64bit, little endian,

getwd: D:\unordered_map
vexe: C:\v\v.exe
vexe mtime: 2024-07-27 02:09:06

vroot: OK, value: C:\v
VMODULES: OK, value: C:\Users\Administrator\.vmodules
VTMP: OK, value: C:\Users\Administrator\AppData\Local\Temp\v_0

Git version: git version 2.45.2.windows.1
Git vroot status: Error: fatal: not a git repository (or any of the parent directories): .git
.git/config present: false

CC version: Error: 'cc' is not recognized as an internal or external command,
operable program or batch file.

thirdparty/tcc: N/A

[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.

baiango commented 1 month ago

Project explanation

I was trying to make a Hash map project in any language that can handle the task. Then found C and C++'s build system was unreliable even with CMake, I am uncertain about will the hash map compile on other system such as Linux and macOS besides Windows. An additional issue is: There was no built-in unit test, which made correctness verification of the hash map very difficult.

Nonetheless, Rust's stringent and over-engineered type system extended the development time quite much, even with the assist of unit test feature. Rust was antagonistic to uninitialized variables.

Thus, I stumbled upon V; realized that it could not compile with the transpiled C code, however, the V code is able to run with the v run command if the code did not get linked to the C code.

My additional concerns are, the base binary (300 KiB) is almost double the size of the original C GCC compiled binary. And lastly, V does not support AVX2 intrinsic beyond x86 assembly in its error message. But, I am able to compile the V code with the novel command v -gc none -manualfree -prod -cc gcc -cflags "-O2 -mavx2 -Wall" crun main.v.

Example of how to write AVX2 intrinsic in C

#include <immintrin.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdalign.h>

bool compare_ymm(const void *a, const void *b) {
    bool result;
    __asm__ (
        "vmovdqa %1, %%ymm0\n\t"
        "vpxor   %2, %%ymm0, %%ymm0\n\t"
        "vptest  %%ymm0, %%ymm0\n\t"
        "sete    %0\n\t"
        "vzeroupper\n\t"
        : "=r" (result)
        : "m" (*(const __m256i *)a), "m" (*(const __m256i *)b)
        : "ymm0"
    );
    return result;
}

int main() {
    alignas(32) unsigned long long a[4] = {1, 2, 3, 4};
    alignas(32) unsigned long long b[4] = {1, 2, 3, 4};

    bool result = compare_ymm(a, b);

    if (result) {
        printf("The two arrays are equal.\n");
    } else {
        printf("The two arrays are not equal.\n");
    }

    return 0;
}
felipensp commented 1 month ago

error: unknown register %ymm0 is not a V error, it is from tcc.

Using v -cg -cc gcc run bug.v you will get:

/tmp/v_1000/bug.01J3T5HXC7AVCRC7DPJGB4QQ4E.tmp.c: Assembler messages:
/tmp/v_1000/bug.01J3T5HXC7AVCRC7DPJGB4QQ4E.tmp.c:13245: Error: operand type mismatch for `vmovdqa'
/tmp/v_1000/bug.01J3T5HXC7AVCRC7DPJGB4QQ4E.tmp.c:13245: Error: operand type mismatch for `vpxor'
Delta456 commented 1 month ago

I believe 2..x / 2 + 1 is the issue because it is invalid

baiango commented 1 month ago

I apologize for rubbing people the wrong way. The issue was about getting manual AVX2 intrinsic to work in V without the compiling error and usable.

JalonSolov commented 1 month ago

I believe 2..x / 2 + 1 is the issue because it is invalid

It is only invalid because V doesn't have a runtime. At runtime, you could check the value of x and decide then whether it's a valid range or not. For example, if x >= 4, it's fine. It should only be an invalid range if x <= 3.

However, with only being able to check at compile time, it is better to mark is is invalid due to the right side not being a constant/literal value that's >= 3.