error: '#snprintf' defined with type 'i32 (i8*, i32, i8*, ...)*' - llvm

I have an LLVM IR code that looks something like this:
declare i32 #snprintf(i8*, i32, i8*, ...)
define i32 #main () {
...
%9 = load i8*, i8** %8
%10 = load i8*, i8** %2
%11 = load i8*, i8** %0
%12 = load i8, i8* %11
%13 = call i32 (i8*, i32, i8*, ...)* #snprintf(i8* %10, i32 3, i8* %9, i8 %12)
...
The last line raise this:
error: '#snprintf' defined with type 'i32 (i8*, i32, i8*, ...)*'
%13 = call i32 (i8*, i32, i8*, ...)* #snprintf(i8* %10, i32 3, i8* %9, i8 %12)
I have researched the LLVM documentation but I can't figure out what's wrong. :-(
Thanks in advance!

I solved the problem. Just removed the * after call type's parenthesis:
%13 = call i32 (i8*, i32, i8*, ...) #snprintf(i8* %10, i32 3, i8* %9, i8 %12)

Related

LLVM asserts "Resolving symbol with incorrect flags"

I'm following the example of Kaleidoscope to write a minimum IR file interpreter. It takes one command line argument, which is a path to .ll file, and executes the main function in the file. But when I tested it on an IR file, it failed with:
Assertion failed: (KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) && "Resolving symbol with incorrect flags", file <path>\llvm\lib\ExecutionEngine\Orc\Core.cpp, line 2775
Considering the simplicity of my code (which only has 63 lines), I can't figure out what's wrong in it. Please help 😭!!!
Full Source Code
#include <iostream>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/ExecutionEngine/Orc/CompileUtils.h>
#include <llvm/ExecutionEngine/Orc/Core.h>
#include <llvm/ExecutionEngine/Orc/ExecutionUtils.h>
#include <llvm/ExecutionEngine/Orc/ExecutorProcessControl.h>
#include <llvm/ExecutionEngine/Orc/IRCompileLayer.h>
#include <llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h>
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
using namespace llvm;
int
main(int argc, char* argv[])
{
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
orc::ThreadSafeContext tsctx(std::make_unique<LLVMContext>());
SMDiagnostic error;
auto mod = parseIRFile(argv[1], error, *tsctx.getContext());
auto epc = orc::SelfExecutorProcessControl::Create();
cantFail(epc.takeError());
orc::ExecutionSession es(std::move(*epc));
auto triple = es.getExecutorProcessControl().getTargetTriple();
orc::JITTargetMachineBuilder jtmb(triple);
auto dl = jtmb.getDefaultDataLayoutForTarget();
cantFail(dl.takeError());
orc::RTDyldObjectLinkingLayer ol(
es, []() { return std::make_unique<SectionMemoryManager>(); });
orc::IRCompileLayer cl(
es, ol, std::make_unique<orc::ConcurrentIRCompiler>(std::move(jtmb)));
auto& jd = es.createBareJITDylib("jd");
jd.addGenerator(
cantFail(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
dl->getGlobalPrefix())));
cantFail(cl.add(jd, orc::ThreadSafeModule(std::move(mod), tsctx)));
orc::MangleAndInterner mangle(es, *dl);
auto f = es.lookup({ &jd }, mangle("main"));
cantFail(f.takeError());
return reinterpret_cast<int (*)()>(f->getAddress())();
}
Test .ll file
; ModuleID = 'sum.ll'
source_filename = "sum.c"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.29.30133"
%struct._iobuf = type { i8* }
%struct.__crt_locale_pointers = type { %struct.__crt_locale_data*, %struct.__crt_multibyte_data* }
%struct.__crt_locale_data = type opaque
%struct.__crt_multibyte_data = type opaque
$scanf = comdat any
$__local_stdio_scanf_options = comdat any
$"??_C#_02DPKJAMEF#?$CFd?$AA#" = comdat any
#"??_C#_02DPKJAMEF#?$CFd?$AA#" = linkonce_odr dso_local unnamed_addr constant [3 x i8] c"%d\00", comdat, align 1
#__local_stdio_scanf_options._OptionsStorage = internal global i64 0, align 8
; Function Attrs: nounwind uwtable
define dso_local i32 #main() local_unnamed_addr #0 {
%1 = alloca i32, align 4
%2 = bitcast i32* %1 to i8*
call void #llvm.lifetime.start.p0i8(i64 4, i8* nonnull %2) #6
%3 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%4 = load i32, i32* %1, align 4, !tbaa !4
%5 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%6 = load i32, i32* %1, align 4, !tbaa !4
%7 = add nsw i32 %6, %4
%8 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%9 = load i32, i32* %1, align 4, !tbaa !4
%10 = add nsw i32 %7, %9
%11 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%12 = load i32, i32* %1, align 4, !tbaa !4
%13 = add nsw i32 %10, %12
%14 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%15 = load i32, i32* %1, align 4, !tbaa !4
%16 = add nsw i32 %13, %15
%17 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%18 = load i32, i32* %1, align 4, !tbaa !4
%19 = add nsw i32 %16, %18
%20 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%21 = load i32, i32* %1, align 4, !tbaa !4
%22 = add nsw i32 %19, %21
%23 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%24 = load i32, i32* %1, align 4, !tbaa !4
%25 = add nsw i32 %22, %24
%26 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%27 = load i32, i32* %1, align 4, !tbaa !4
%28 = add nsw i32 %25, %27
%29 = call i32 (i8*, ...) #scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* #"??_C#_02DPKJAMEF#?$CFd?$AA#", i64 0, i64 0), i32* nonnull %1)
%30 = load i32, i32* %1, align 4, !tbaa !4
%31 = add nsw i32 %28, %30
call void #llvm.lifetime.end.p0i8(i64 4, i8* nonnull %2) #6
ret i32 %31
}
; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
declare void #llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
; Function Attrs: inlinehint nobuiltin nounwind uwtable
define linkonce_odr dso_local i32 #scanf(i8* %0, ...) local_unnamed_addr #2 comdat {
%2 = alloca i8*, align 8
%3 = bitcast i8** %2 to i8*
call void #llvm.lifetime.start.p0i8(i64 8, i8* nonnull %3) #6
call void #llvm.va_start(i8* nonnull %3)
%4 = load i8*, i8** %2, align 8, !tbaa !8
%5 = call %struct._iobuf* #__acrt_iob_func(i32 0) #6
%6 = call i64* #__local_stdio_scanf_options() #6
%7 = load i64, i64* %6, align 8, !tbaa !10
%8 = call i32 #__stdio_common_vfscanf(i64 %7, %struct._iobuf* %5, i8* %0, %struct.__crt_locale_pointers* null, i8* %4) #6
call void #llvm.va_end(i8* nonnull %3)
call void #llvm.lifetime.end.p0i8(i64 8, i8* nonnull %3) #6
ret i32 %8
}
; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
declare void #llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare void #llvm.va_start(i8*) #3
; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare void #llvm.va_end(i8*) #3
declare dso_local %struct._iobuf* #__acrt_iob_func(i32) local_unnamed_addr #4
declare dso_local i32 #__stdio_common_vfscanf(i64, %struct._iobuf*, i8*, %struct.__crt_locale_pointers*, i8*) local_unnamed_addr #4
; Function Attrs: noinline nounwind uwtable
define linkonce_odr dso_local i64* #__local_stdio_scanf_options() local_unnamed_addr #5 comdat {
ret i64* #__local_stdio_scanf_options._OptionsStorage
}
attributes #0 = { nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { argmemonly mustprogress nofree nosync nounwind willreturn }
attributes #2 = { inlinehint nobuiltin nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #3 = { mustprogress nofree nosync nounwind willreturn }
attributes #4 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #5 = { noinline nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #6 = { nounwind }
!llvm.module.flags = !{!0, !1, !2}
!llvm.ident = !{!3}
!0 = !{i32 1, !"wchar_size", i32 2}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"uwtable", i32 1}
!3 = !{!"clang version 13.0.1"}
!4 = !{!5, !5, i64 0}
!5 = !{!"int", !6, i64 0}
!6 = !{!"omnipotent char", !7, i64 0}
!7 = !{!"Simple C/C++ TBAA"}
!8 = !{!9, !9, i64 0}
!9 = !{!"any pointer", !6, i64 0}
!10 = !{!11, !11, i64 0}
!11 = !{!"long long", !6, i64 0}
Which is compiled from:
#include <stdio.h>
int
main()
{
int n, sum = 0;
for (int i = 0; i < 10; ++i) {
scanf("%d", &n);
sum += n;
}
return sum;
}
Well, it turns out that THERE IS NOTHING WRONG WITH MY CODE!
I compile and test the same code in Linux environment (WSL2), and everything works fine. I'm pretty sure that this is somewhat compatibility problem between Linux and Windows.
Maybe this is a bug of LLVM?

Why is this block of LLVM instructions generated?

The DataFlowSanitizer pass on LLVM 3.8.0, 64 bit (Ubuntu 16.04.2) generates the following IR from source:
The source:
test.c
#include <sanitizer/dfsan_interface.h>
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
return 0;
}
The commands to generate the IR:
clang -c -emit-llvm -fsanitize=dataflow test.c -o test.bc
llvm-dis test.bc
The disassembly:
test.ll
; Function Attrs: nounwind uwtable
define i32 #main() #0 {
entry:
%0 = alloca i16
%retval = alloca i32, align 4
%i = alloca i32, align 4
%1 = alloca i16
%i_label = alloca i16, align 2
store i16 0, i16* %0
store i32 0, i32* %retval, align 4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%2 = ptrtoint i32* %i to i64
%3 = and i64 %2, -123145302310913
%4 = mul i64 %3, 2
%5 = inttoptr i64 %4 to i16*
%6 = bitcast i16* %5 to i64*
store i64 0, i64* %6, align 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
store i32 1, i32* %i, align 4
%call = call zeroext i16 #dfsan_create_label(i8* getelementptr inbounds ([2 x i8], [2 x i8]* #.str, i32 0, i32 0), i8* null)
store i16 0, i16* %1
store i16 %call, i16* %i_label, align 2
%7 = load i16, i16* %1
%8 = load i16, i16* %i_label, align 2
%9 = bitcast i32* %i to i8*
call void #dfsan_set_label(i16 zeroext %8, i8* %9, i64 4)
ret i32 0
}
I don't understand why the block of instruction I separated out is being generated. Looking at the Transform/Instrumentation/DataFlowsanitizer.cpp, I can't find the code that inserts the instrumentation above. Can anyone explain this behavior?

Getting the value stored from register in llvm IR

I have a simple C program.
int
1.main(int argc, char **argv) {
2. unsigned buffer[4] = { 0, 0, 0, 0 };
3. return buffer[argc];
4. }
And the IR code is as below
; Function Attrs: norecurse nounwind readnone uwtable
define i32 #main(i32 %argc, i8** nocapture readnone %argv) #0 !dbg !6 {
%buffer = alloca [4 x i32], align 16
tail call void #llvm.dbg.value(metadata i32 %argc, i64 0, metadata !14, metadata !21), !dbg !22
tail call void #llvm.dbg.value(metadata i8** %argv, i64 0, metadata !15, metadata !21), !dbg !23
%1 = bitcast [4 x i32]* %buffer to i8*, !dbg !24
call void #llvm.lifetime.start(i64 16, i8* %1) #3, !dbg !24
tail call void #llvm.dbg.declare(metadata [4 x i32]* %buffer, metadata !16, metadata !21), !dbg !25
call void #llvm.memset.p0i8.i64(i8* %1, i8 0, i64 16, i32 16, i1 false), !dbg !26
%2 = sext i32 %argc to i64, !dbg !28
%3 = getelementptr inbounds [4 x i32], [4 x i32]* %buffer, i64 0, i64 %2, !dbg !28
%4 = load i32, i32* %3, align 4, !dbg !28, !tbaa !29
call void #llvm.lifetime.end(i64 16, i8* %1) #3, !dbg !33
ret i32 %4, !dbg !34
}
I want to compare whether the accessing index at line 3 is a valid index. For this comparison I need to extract the value stored for the argc. Below is piece of code I have written to obain the vvalue of argc
auto gep = llvm::dyn_cast<llvm::GetElementPtrInst>(inst);
auto operand2 = gep->getOperand(2);
outs() << "operand 2 "<<*operand2<<"\n";
auto newOperand =operand2.getOperand(0);
outs()<<"New operand "<<*newOperand<<"\n";
Output :-
operand 2 %2 = sext i32 %argc to i64, !dbg !28
New operand i32 %argc
How can I get the value of %argc?
The return value of getOperand function is Value* object of the argc variable (variable newOperand in your code). You can pass that value to any new instruction that you might want to inject (for example CreateICmpEQ) in the IR to compare value of argc with some constant value.

LLVM Create VarArg Function and access var args

I have been trying to create a function using the module pass in LLVM. What I am trying to do is create a variable argument function and then add the logic to manipulate the variable arguments.
For example:
/\*can do this\*/
int foo(int a, ...)
{
double var1;
//can't figure out how to add any of this using llvm
va_list ap;
va_start(ap, a);
va_arg(var1,double);
va_end(ap);
}
Creating the function type is easy because I just set the vararg boolean to true. What do I do after that?
I always use clang to check what it needs to convert for c/c++ lang.
Use llvm instruction va_arg and intinsics llvm.va_start, llvm.va_end, llvm.va_copy to use llvm variable argument support.
you also need target-specific value type “va_list” for functions that operates on arguments that use this.
; This struct is different for every platform. For most platforms,
; it is merely an i8*.
%struct.va_list = type { i8* }
; For Unix x86_64 platforms, va_list is the following struct:
; %struct.va_list = type { i32, i32, i8*, i8* }
ref http://llvm.org/docs/LangRef.html#variable-argument-handling-intrinsics
for your listed code,
; ModuleID = 'test.c'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
%struct.__va_list_tag = type { i32, i32, i8*, i8* }
; Function Attrs: nounwind uwtable
define i32 #foo(i32 %a, ...) #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%var1 = alloca double, align 8
%ap = alloca [1 x %struct.__va_list_tag], align 16
store i32 %a, i32* %2, align 4
%3 = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0
%4 = bitcast %struct.__va_list_tag* %3 to i8*
call void #llvm.va_start(i8* %4)
%5 = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0
%6 = getelementptr inbounds %struct.__va_list_tag* %5, i32 0, i32 1
%7 = load i32* %6
%8 = icmp ule i32 %7, 160
br i1 %8, label %9, label %15
; <label>:9 ; preds = %0
%10 = getelementptr inbounds %struct.__va_list_tag* %5, i32 0, i32 3
%11 = load i8** %10
%12 = getelementptr i8* %11, i32 %7
%13 = bitcast i8* %12 to double*
%14 = add i32 %7, 16
store i32 %14, i32* %6
br label %20
; <label>:15 ; preds = %0
%16 = getelementptr inbounds %struct.__va_list_tag* %5, i32 0, i32 2
%17 = load i8** %16
%18 = bitcast i8* %17 to double*
%19 = getelementptr i8* %17, i32 8
store i8* %19, i8** %16
br label %20
; <label>:20 ; preds = %15, %9
%21 = phi double* [ %13, %9 ], [ %18, %15 ]
%22 = load double* %21
%23 = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0
%24 = bitcast %struct.__va_list_tag* %23 to i8*
call void #llvm.va_end(i8* %24)
%25 = load i32* %1
ret i32 %25
}
; Function Attrs: nounwind
declare void #llvm.va_start(i8*) #1
; Function Attrs: nounwind
declare void #llvm.va_end(i8*) #1
; Function Attrs: nounwind uwtable
define i32 #main() #0 {
ret i32 0
}

How to execute llvm code

I have a c code that calculates the factorial of an int "factorial.c". I compile it to llvm readable code "factorial.ll" and I modify in the compiled llvm code.
The objective is to execute the modified llvm code and to see its output, How can I do this?
It will depend on how your outputted LLVM is assembled and what libraries it links against, but for example executing the following factorial.ll with the shell command lli
$ lli factorial.ll
Factorial of 10 = 3628800
Will execute the main function with the JIT and use the standard printf to output the result to stdout.
#.str = private unnamed_addr constant [22 x i8] c"Factorial of %d = %d\0A\00", align 1
declare i32 #printf(i8*, ...)
define i32 #factorial(i32 %n) nounwind uwtable {
entry:
%n.addr = alloca i32, align 4
store i32 %n, i32* %n.addr, align 4
%0 = load i32* %n.addr, align 4
%cmp = icmp sle i32 %0, 1
br i1 %cmp, label %cond.true, label %cond.false
cond.true: ; preds = %entry
br label %cond.end
cond.false: ; preds = %entry
%1 = load i32* %n.addr, align 4
%2 = load i32* %n.addr, align 4
%sub = sub nsw i32 %2, 1
%call = call i32 #factorial(i32 %sub)
%mul = mul nsw i32 %1, %call
br label %cond.end
cond.end: ; preds = %cond.false, %cond.true
%cond = phi i32 [ 1, %cond.true ], [ %mul, %cond.false ]
ret i32 %cond
}
define i32 #main(i32 %argc, i8** %argv) nounwind uwtable {
entry:
%retval = alloca i32, align 4
%argc.addr = alloca i32, align 4
%argv.addr = alloca i8**, align 8
store i32 0, i32* %retval
store i32 %argc, i32* %argc.addr, align 4
store i8** %argv, i8*** %argv.addr, align 8
%call = call i32 #factorial(i32 10)
%call1 = call i32 (i8*, ...)* #printf(i8* getelementptr inbounds ([22 x i8]* #.str, i32 0, i32 0), i32 10, i32 %call)
ret i32 0
}