I am trying to instrument LLVM IR generated by the swift compiler and in particular, I want to record at runtime the read and write operations to an array. Since in Swift the actual read does not happen in the IR through a load instruction but rather through a call to the stdlib my idea was to generate some instructions that should obtain this information. In particular:
types:
%TSa = type <{ %Ts22_ContiguousArrayBufferV }>
%Ts22_ContiguousArrayBufferV = type <{ %Ts28__ContiguousArrayStorageBaseC* }>
%Ts28__ContiguousArrayStorageBaseC = type opaque
Instructions for reading from array:
%20 = load %Ts28__ContiguousArrayStorageBaseC*, %Ts28__ContiguousArrayStorageBaseC** getelementptr inbounds (%TSa, %TSa* @"$array", i32 0, i32 0, i32 0), align 8, !dbg !40
%21 = call swiftcc i64 @"$sSayxSicigSi_Tg5"(i64 0,%Ts28__ContiguousArrayStorageBaseC* %20), !dbg !40
the first instruction loads the base of the array into register 20, the a call to the stdlib with the index 0 as argument reads the value into register 21. My idea is to issue a getelementptr instruction that calculates the actual index and then passes it to a function that calls my own runtime lib to record the access like so:
%20 = load %Ts28__ContiguousArrayStorageBaseC*, %Ts28__ContiguousArrayStorageBaseC** getelementptr inbounds (%TSa, %TSa* @"$array", i32 0, i32 0, i32 0), align 8, !dbg !40
%21 = call swiftcc i64 @"$sSayxSicigSi_Tg5"(i64 0,%Ts28__ContiguousArrayStorageBaseC* %20), !dbg !40
%22 = getelementptr % Ts28__ContiguousArrayStorageBaseC, % Ts28__ContiguousArrayStorageBaseC* 28, i64 0, i64 0
however I am getting the error
**llvm::Type llvm::checkGEPType(llvm::Type): Assertion Ty && “Invalid GetElementPtrInst indices for type!”’ failed
The arguments I give to GetElementPtrInst::Create look like this when I print them:
%Ts28__ContiguousArrayStorageBaseC = type opaque
%26 = load %Ts28__ContiguousArrayStorageBaseC*
%Ts28__ContiguousArrayStorageBaseC** getelementptr inbounds (%TSa, %TSa* @"$s9reduction3arrSaySiGvp", i32 0, i32 0, i32 0), align 8
i64 0
i64 0
did I mess up with the typing or something? As I understand it, the base type of my getelementptr instruction is now TSa but I think it should be Ts28__ContiguousArrayStorageBaseC but then I do not understand what exactly type opaque means… My LLVM understanding is not that great yet as I am just starting to learn it.
thanks!
edit:
so I solved it with an add instruction and a cast for now but I think a getelementptr instruction would be more appropriate? this is what I came up with:
%26 = load %Ts28__ContiguousArrayStorageBaseC*, %Ts28__ContiguousArrayStorageBaseC** getelementptr inbounds (%TSa, %TSa* @"$s9reduction3arrSaySiGvp", i32 0, i32 0, i32 0), align 8
%28 = call swiftcc i64 @"$sSayxSicigSi_Tg5"(i64 0, %Ts28__ContiguousArrayStorageBaseC* %26)
%27 = ptrtoint %Ts28__ContiguousArrayStorageBaseC* %26 to i64
%idxadd = add i64 0, %27
call void @read(i32 16388, i64 %idxadd, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.1, i32 0, i32 0))
with the read call being to my library for recording the read operation.