nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.55k stars 1.47k forks source link

Compiler segfaults when comptime accessing a c macro constant bound to a compTime let with importc #22242

Open MCRusher opened 1 year ago

MCRusher commented 1 year ago

Description

I'm currently writing a wrapper over Vulkan since I couldn't find an existing one and I'm trying to directly bind macro constants to nim constants to prevent the values from potentially shifting out from under me in the future, but that causes a different compiler error where the constant still expects an initializer value and just ignores the importc pragma.

So instead I bound it to a let variable with the compTime pragma and this compiles, I can even echo it and it works fine, but as soon as I try to use it in a comptime context (as the size of an array, in a when statement, etc.) the compiler segfaults and crashes.

Minimum reproducible code:

ctest.h

#ifndef CTEST_H
#define CTEST_H

#define MACRO_CONSTANT 4

#endif

ctest.nim

let MacroConstant {.importc: "MACRO_CONSTANT", header: "\"ctest.h\"", compileTime.}: int

echo MacroConstant # correctly prints 4

#let arr: array[MacroConstant, int] # uncomment this line and compiler segfaults

Nim Version

Nim Compiler Version 1.9.5 [Linux: amd64] Compiled at 2023-07-08 Copyright (c) 2006-2023 by Andreas Rumpf

git hash: 6ec10a4c9182c513fecd17fde4a81a3a007bb2e9 active boot switches: -d:release

Current Output

Hint: used config file '/home/USER/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/USER/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
......................................................................SIGSEGV: Illegal storage access. (Attempt to read from nil?)

Expected Output

Hint: used config file '/home/USER/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/USER/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
......................................................................
Hint:  [Link]
Hint: mm: orc; threads: on; opt: none (DEBUG BUILD, `-d:release` generates faster code)
27605 lines; 0.124s; 30.32MiB peakmem; proj: /home/USER/Documents/cTest/ctest.nim; out: /home/USER/Documents/cTest/ctest [SuccessX]

Possible Solution

No response

Additional Information

I'm not sure if what I'm trying to do is even supposed to be allowed by the language, but I figured that at least the segfault was noteworthy.

beef331 commented 1 year ago

To clear it up, let is not static so it should statically error about usage in a static context.

demotomohiro commented 1 year ago

Nim compiler doesn't read C code. You provide information about functions, types, variables or constants in C code, and Nim generate C code that use them. So Nim can access macros in C at runtime, but cannot at compile-time.

I found existing wrappers over Vulkan for Nim: https://github.com/nimious/vulkan https://github.com/nimgl/vulkan

Even if you create a wrapper over Vulkan yourself, you might better to write a generater that reads xml/vk.xml in following repositry and generate a Nim code that exports Vulkan APIs. https://github.com/KhronosGroup/Vulkan-Docs#generating-headers-and-related-files This repo says Vulkan header files are generated from that xml file. Vulkan Bindings for Nim also seems to generate binding in that way. https://github.com/nimgl/vulkan/blob/master/tools/generator.nim

MCRusher commented 1 year ago

Nim compiler doesn't read C code. You provide information about functions, types, variables or constants in C code, and Nim generate C code that use them. So Nim can access macros in C at runtime, but cannot at compile-time.

I'm aware it doesn't read the C code. But if I tell Nim that a compiletime-constant macro value exists I feel like it should be able to use it as a constant in the C code it generates rather than only at runtime. If that's not possible currently/ever, that's fine, I just wanted to know if there was an intended way to do it or not.

But that's not really why I made this bug report, I made it because the compiler crashes, it probably shouldn't do that.

Thanks for mentioning nimgl, I didn't realize it had a wrapper for vulkan as well.

Although I was definitely learning a lot about C interop with nim which is nice to know, like how you can use a nim enum set to represent a C bitmask in a much nicer way, but you have to explicitly set the size pragma to ensure it's correct.

beef331 commented 1 year ago

But if I tell Nim that a compiletime-constant macro value exists I feel like it should be able to use it as a constant in the C code it generates rather than only at runtime.

The issue with that is array[size, T] is static inside Nim, so it needs to know what size is to be able to dispatch and generate code accordingly. Which requires understanding C code.