How to halt a program

Guys,

I would like to instrument the bytecode that LLVM produces with assertions. I have written the instrumentation code manually, but I do not know how to halt the program in case the assertion is false. I took a look into the bytecode that LLVM produces for a program like:

#include <stdlib.h>
int main() {
exit(1);
}

And it is like this:

define i32 @main() nounwind {
entry:
%retval = alloca i32 ; <i32*> [#uses=1]
%0 = alloca i32 ; <i32*> [#uses=0]
%“alloca point” = bitcast i32 0 to i32 ; [#uses=0]
call void @exit(i32 1) noreturn nounwind
unreachable
return: ; No predecessors!
%retval1 = load i32* %retval ; [#uses=1]
ret i32 %retval1
}

So, what is the LLVM code to insert the call “call void @exit(i32 1) noreturn nounwind”? I thought about something like:

CallInst abort = CallInst::Create(/POINTER TO ABORT/, ArrayRef<Value>(), Twine(), assertfail);
abort->addAttribute(~0, Attribute::NoReturn);
abort->addAttribute(~0, Attribute::NoUnwind);

However, I do not know what to fill up in /POINTER TO ABORT/. Can anyone help me?

Thank you very much,

Victor

Victor Campos wrote:

Guys,

     I would like to instrument the bytecode that LLVM produces with
assertions. I have written the instrumentation code manually, but I do
not know how to halt the program in case the assertion is false. I took
a look into the bytecode that LLVM produces for a program like:

#include <stdlib.h>
int main() {
   exit(1);
}

And it is like this:

define i32 @main() nounwind {
entry:
   %retval = alloca i32 ; <i32*> [#uses=1]
   %0 = alloca i32 ; <i32*> [#uses=0]
   %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
   call void @exit(i32 1) noreturn nounwind
   unreachable
return: ; No predecessors!
   %retval1 = load i32* %retval ; <i32> [#uses=1]
   ret i32 %retval1
}

So, what is the LLVM code to insert the call "call void @exit(i32 1)
noreturn nounwind"? I thought about something like:

CallInst *abort = CallInst::Create(/*POINTER TO ABORT*/,
ArrayRef<Value*>(), Twine(), assertfail);
abort->addAttribute(~0, Attribute::NoReturn);
abort->addAttribute(~0, Attribute::NoUnwind);

However, I do not know what to fill up in /*POINTER TO ABORT*/. Can
anyone help me?

Something like:

// Once, M = llvm::Module*, C = LLVMContext&:
FunctionType *AbortFTy = FunctionType::get(Type::getVoidTy(C), false);
Function *AbortF = Function::Create(AbortFTy, GlobalValue::ExternalLinkage, "abort", M);

// Each call site:
CallInst *abort = CallInst::Create(AbortF, ...

Nick

Hi, all,

I managed to insert the assertion in my bytecode, but the result is not really what I expected :frowning:

Let me do a quick recap: I am trying to instrument the bytecode with some assertions, and to do this, I want to insert the abort() function into the bytecode. The problem is that LLVM is creating a new abort() function, instead of using the one that already exists in libc. Let me show my code to add the abort into the code:

// Create abort function
FunctionType *AbortFTy = FunctionType::get(Type::getVoidTy(*context), false);
Function *AbortF = Function::Create(AbortFTy, GlobalValue::ExternalLinkage, “abort”, &M);

// Call to abort function
CallInst *abort = CallInst::Create(AbortF, Twine(), assertfail);

// Add atributes to the abort call instruction: no return and no unwind
abort->addAttribute(~0, Attribute::NoReturn);
abort->addAttribute(~0, Attribute::NoUnwind);

// Unreachable instruction
new UnreachableInst(*context, assertfail);

So, my bytecode now looks like this one below:

define i32 @main() nounwind {

“assert fail”: ; preds = %bb1, %13, %bb, %3, %entry
call void @abort() noreturn nounwind
unreachable

}

define void @abort() {
“assert fail”:
call void @abort() noreturn nounwind
unreachable
}

But, in truth, what I really wanted to do is to create a bytecode like the one below:

define i32 @main() nounwind {

bb2: ; preds = %bb, %entry
call void @abort() noreturn nounwind
unreachable
}

declare void @abort() noreturn nounwind

So, could some of you tell me what I need to do to get this “declare void @abort …” into my bytecode, instead of the “define void @abort…”?

Thank you very much,

Victor

2011/8/19 Nick Lewycky <nicholas@mxc.ca>

Hi Victor,

bytecode. The problem is that LLVM is creating a new abort() function, instead
of using the one that already exists in libc.

from the bitcode you show, the problem is that you are adding statements to
the abort function turning it from a declaration into a definition.

> define void @abort() {
> "assert fail":
> call void @abort() noreturn nounwind
> unreachable
> }

Don't add the basic block "assert fail" and its contents to function "abort",
only add them to "main".

Ciao, Duncan.