295 debug <<
"AppendInstrumentation\n";
297 LLVMContext& Ctx = InstrFn->getContext();
298 auto *Head = dyn_cast<FieldAssignTransition>(*Trans.begin());
300 auto& Protobuf = Head->Assignment();
304 auto& Params = InstrFn->getArgumentList();
305 assert(Params.size() == 3);
307 auto i = Params.begin();
308 llvm::Argument *Struct = &*i++;
309 llvm::Argument *NewValue = &*i++;
310 llvm::Argument *FieldPtr = &*i++;
314 SmallVector<Value*,2> KeyValues;
315 KeyValues.push_back(Struct);
318 auto *End = NextInstrBlock(&A);
319 auto *Instr = BasicBlock::Create(Ctx, Head->ShortLabel(), InstrFn, End);
320 End->replaceAllUsesWith(Instr);
321 IRBuilder<> Builder(Instr);
326 auto& ExpectedAssignment = Protobuf.value();
328 switch (ExpectedAssignment.type()) {
331 IntegerType *ValueType = dyn_cast<IntegerType>(NewValue->getType());
333 panic(
"NewValue not an integer type");
335 auto *Match = BasicBlock::Create(Ctx,
"match: " + Head->ShortLabel(),
337 Instr->replaceAllUsesWith(Match);
338 IRBuilder<> Matcher(Match);
340 auto *Const = ConstantInt::getSigned(ValueType, ExpectedAssignment.value());
343 switch (Protobuf.operation()) {
348 case FieldAssignment::PlusEqual:
349 Expected = Matcher.CreateAdd(Matcher.CreateLoad(FieldPtr), Const);
353 Expected = Matcher.CreateSub(Matcher.CreateLoad(FieldPtr), Const);
357 Matcher.CreateCondBr(Matcher.CreateICmpNE(NewValue, Expected), End, Instr);
361 case Argument::Variable:
362 KeyValues.push_back(NewValue);
366 panic(
"'ANY' value should never be passed to struct field instrumentation");
368 case Argument::Indirect:
369 panic(
"struct field instrumentation should not be passed indirect value");
372 panic(
"struct field instrumentation should not be passed struct field");
375 Type* IntType = Type::getInt32Ty(Ctx);
377 std::vector<Value*> Args;
378 Args.push_back(
TeslaContext(A.getAssertion().context(), Ctx));
379 Args.push_back(ConstantInt::get(IntType, A.ID()));
381 Args.push_back(Builder.CreateGlobalStringPtr(A.Name()));
382 Args.push_back(Builder.CreateGlobalStringPtr(A.String()));
386 assert(Args.size() == UpdateStateFn->arg_size());
387 Builder.CreateCall(UpdateStateFn, Args);
388 Builder.CreateBr(Exit);