Hi community, I‘m studying TVM and its low-level operators recently. These days I tried to construct some simple loops, and I found an undefined behavior may occur if we cast string to a boolean value.
As listed below, I cast string to bool as the condition of a While loop, I found it will crash if I build the module several times.
import tvm
from tvm import tir
v = tir.Cast('bool', tvm.runtime.convert("a"))
body = tir.stmt.While(v, body=tir.Evaluate(tir.const(0)))
func = tir.PrimFunc(params={}, body=body)
mod = tvm.lower(func)
nopt_mod = tvm.build(mod)
nopt_mod = tvm.build(mod)
I build the latest TVM on my server, with Ubuntu 18.04 and llvm-12, after executing my code, I got such a crash message:
(tvm-build) ➜ ~ python3 cast_str.py
[1] 33220 segmentation fault (core dumped) python3 cast_str.py
To find the root cause, I read the source and found the function CodeGenLLVM::CreateCast doesn’t consider the case casting from handle to int. If to.is_uint() && to.bits() == 1 exists and from is not float number, it will be treated as an Int type.
Since we pass StringImm, whose dtype is handle, as the original type, it will be treated as an int and finally cause undefined behavior, like such crash.
llvm::Value* CodeGenLLVM::CreateCast(DataType from, DataType to, llvm::Value* value) {
llvm::Type* target = DTypeToLLVMType(to);
if (value->getType() == target) return value;
if (to.is_handle()) {
return builder_->CreateBitCast(value, target);
} else if (to.is_uint() && to.bits() == 1) {
if (from.is_float()) {
llvm::Constant* zero = llvm::ConstantFP::get(DTypeToLLVMType(from), 0.);
return builder_->CreateFCmpONE(value, zero);
} else {
llvm::Constant* zero = llvm::ConstantInt::get(DTypeToLLVMType(from), 0);
return builder_->CreateICmpNE(value, zero);
}
} else if (!from.is_float() && !to.is_float()) {
return builder_->CreateIntCast(value, target, from.is_int());
} else if (from.is_float() && to.is_int()) {
return builder_->CreateFPToSI(value, target);
} else if (from.is_float() && to.is_uint()) {
if (to.bits() < 8) {
value = builder_->CreateFPToUI(value, DTypeToLLVMType(to.with_bits(8)));
return builder_->CreateIntCast(value, target, false);
} else {
return builder_->CreateFPToUI(value, target);
}
} else if (from.is_int() && to.is_float()) {
return builder_->CreateSIToFP(value, target);
} else if (from.is_uint() && to.is_float()) {
return builder_->CreateUIToFP(value, target);
} else {
ICHECK(from.is_float() && to.is_float());
return builder_->CreateFPCast(value, target);
}
}
I’m curious whether casting string to boolean is a legal behavior in TVM, if yes, how can we fix this bug? Or if not, it will be better if we provide some tips to developers to prevent it. I would be grateful if anyone can help me 

