I need to know if there's a way to prevent LLVM from linking in CRT symbols entirely. The goal is to make a new runtime.
I have a stub library written in my language, when I go to compile the library in .lib form, I keep running into a wall where LLVM forcefully brings in _fltused, causing my definition to get flagged with an error saying _fltused already exists.
There is nothing in the .ll IR file other than the _fltused definition, the one that I want to have end up in the final .lib.
I have Googled and asked AI for days now what compiler/linker flags I can use to get LLVM to bypass the CRT entirely so I can develop my own runtime, and Clang, MinGW, and LLVM are all aggressively linking in the CRT no matter what flags I add.
I'm pulling my hair out over here. I can't convert my .ll file directly to .as because the LLVM compiler is getting in the way, otherwise I'd have my library by now.
If you can't find it in the code, my recommendation is to just delete the CRT files and see who screams.
Once you've found it, check up the call stack (either by running a debugger or looking for calls to the functions in the source) and see if any of them have if statements.
If truly not a single conditional is present between main() and linking the CRT, you may just want to add one and submit a patch.
If you can edit your post it would also be helpful to know which flags you've already tried.
Sounds like this is about making .OBJs that fit in the conventions set by Win32 and the Microsoft linker. If you were using Microsoft's LINK.EXE I'd look at https://learn.microsoft.com/en-us/cpp/build/reference/nodefa... (and /Zi for the Microsoft compiler)
More generally, a lot of compiler generated code (including from LLVM IR -> native) will rely on compiler-specific runtime library functions, which aren't necessarily considered part of the "C runtime". https://wiki.osdev.org/Libgcc occupies this role for GCC-compiled code. See https://godbolt.org/z/fb75PPobz for an example (64-bit division on 32-bit x86 generates a call to ___divdi3)
These references do not appear in the .ll file. They are injected when the .ll file is compiled to object files.
I think something in your code triggers a reference to one of the other injected functions and that pulls in the CRT.
Try compiling your test file into an .o or .obj, that is, without linking. Then dump the symbols in the object file to see what symbols are referenced. I suspect you'll see other references to symbols in CRT and you will have to replace those as well with stubs.
Unfortunately, I don't remember the linker flags to replace/suppress the default CRT libs. Well, actually, you might compile to .o / .obj and then manually link on your system. If you're using MSVC check the options to its "link" executable (I don't remember the exact name of the MSVC linker).
On x86 only, if you need to cast floats, try /QIfist (deprecated) to avoid hitting _ftol. Doesn't work for x64 or ARM.
One other thing you may want to try is writing a linker script manually. If you could provide the linker flags as mentioned elsewhere, that would be useful.
TLDR it's going to emit the reference if it's targeting MSVC and there's any float typed reference. You'd need to do something to avoid it, other than avoiding float types.
Presumably you are compiling for the MSVC ABI. Trying to plug your own runtime that doesn't behave exactly as the MSVC scheme isn't going to just work out of the box. The compiler has to know the details of the ABI you are targeting, if you're doing your own thing the compiler would need to treat that as a separate ABI. I'm not sure there's a triple now that means MSVC-like-freestanding.
The same logic applies on the clang driver side. The ABI expects to link those libraries, so it will.