LLVM Discussion Forums

Store instruction with confusing pointer value using constant inttoptr

Hello,

while working with LLVM IR, I encountered a confusing store instruction:

store %struct.ucl_object_s* null, %struct.ucl_object_s** inttoptr (i64 24 to %struct.ucl_object_s**), align 8, !dbg !10759, !tbaa !2415

where %struct.ucl_object_s is a type:

%struct.ucl_object_s = type { %union.anon, i8*, %struct.ucl_object_s*, %struct.ucl_object_s*, i32, i32, i32, i16, i16, [2 x i8*] }
%union.anon = type { i64 }

I am confused because I expect the pointer for this instruction to, well, actually point to something. Instead, it seems like the pointer is just the value 24 casted as a pointer to (a pointer to) that struct. However, in context of the original source code I would expect this pointer calculation to at least involve a local variable.

The source code line, that according to the debug information is responsible for this instruction: https://github.com/vstakhov/libucl/blob/10c4dada6229122b1f9a09dcbe43d6bd2d229dc6/src/ucl_util.c#L1209

I am also applying the reg2mem pass to the bitcode module, in case that could help.
The basic block containing the instruction:

277:                                              ; preds = %266
  call void @llvm.dbg.value(metadata %struct.ucl_object_s* %275, metadata !10418, metadata !DIExpression()), !dbg !10434
  store %struct.ucl_object_s* null, %struct.ucl_object_s** inttoptr (i64 24 to %struct.ucl_object_s**), align 8, !dbg !10759, !tbaa !2415
  store %struct.ucl_object_s* null, %struct.ucl_object_s** inttoptr (i64 16 to %struct.ucl_object_s**), align 16, !dbg !10760, !tbaa !2373
  call void @llvm.dbg.value(metadata %struct.ucl_object_s* %.reload1051, metadata !8429, metadata !DIExpression()) #9, !dbg !10761
  call void @llvm.dbg.value(metadata %struct.ucl_object_s* %275, metadata !8430, metadata !DIExpression()) #9, !dbg !10761
  call void @llvm.dbg.value(metadata %struct.ucl_array_t* %292, metadata !8431, metadata !DIExpression()) #9, !dbg !10761
  %.reload603 = load %struct.ucl_hash_struct*, %struct.ucl_hash_struct** %.reg2mem602
  store %struct.ucl_hash_struct* %.reload603, %struct.ucl_hash_struct** %.reg2mem998
  store %struct.ucl_object_s* null, %struct.ucl_object_s** %.reg2mem1000
  br label %641, !dbg !10763

If someone could explain what this store instruction is actually doing, I would be very thankful.

The line your pointing at look like:

				nest_obj->prev = nest_obj;

In general if you see a store to the address 24 here it likely indicates that nest_obj is provably a nullptr (or some UB lead it to this) and prev is at the offset 24 in the structure nest_obj.

Thank you very much for that answer!
In hindsight it is actually quite obvious.