I'm trying to convert an i32 (integer) to an i8 pointer (string) by creating a buffer and adding to it using sprintf like in C. However, this does not work because I get an error saying that sprintf is unresolved when linking.
error LNK2019: unresolved external symbol sprintf referenced in function main
module = ctx.scope.module
builder: ir.IRBuilder = ctx.scope.builder
sprintf = ctx.compiler.get_func('sprintf', ir.FunctionType(
int.type, [string.type, string.type], var_arg=True
))
INT_BUF_SIZE = 16
fmt_type = ir.ArrayType(ir.IntType(8), 3)
fmt_str = ir.GlobalVariable(module, fmt_type, module.get_unique_name())
fmt_str.initializer = ir.Constant(fmt_type, bytearray(b'%d\0'))
buf_type = ir.ArrayType(ir.IntType(8), INT_BUF_SIZE)
buf = builder.alloca(buf_type)
zero = ir.Constant(ir.IntType(32), 0)
fmt_ptr = builder.gep(fmt_str, [zero, zero])
buf_ptr = builder.gep(buf, [zero, zero])
builder.call(sprintf, [fmt_ptr, buf_ptr, value])
printf works just fine but it's just sprintf that doesn't seem to work.
I have also tried snprintf and sprintf_s - both do compile without errors but when I try running the resulting .exe file, the program crashes.
I have also tried asking AI but the best it could do is add -lmsvcrt (I am on Windows) to the clang command.
This is the LLVM IR that gets outputted by my compiler
; ModuleID = "main"
target triple = "x86_64-pc-windows-msvc"
target datalayout = ""
define i32 @"main"()
{
.2:
%".3" = getelementptr [4 x i8], [4 x i8]* @".1", i32 0, i32 0
%".4" = alloca [16 x i8]
%".5" = getelementptr [3 x i8], [3 x i8]* @".2", i32 0, i32 0
%".6" = getelementptr [16 x i8], [16 x i8]* %".4", i32 0, i32 0
%".7" = call i32 (i8*, i8*, ...) @"sprintf"(i8* %".5", i8* %".6", i32 25)
%".8" = call i32 (i8*, ...) @"printf"(i8* %".3", i8* %".6")
ret i32 0
}
declare i32 @"printf"(i8* %".1", ...)
@".1" = constant [4 x i8] [i8 37, i8 115, i8 10, i8 0]
declare i32 @"sprintf"(i8* %".1", i8* %".2", ...)
@".2" = global [3 x i8] c"%d\00"