Computer Laboratory

tesla::FieldInstrumentation Class Reference

Detailed Description

Instrumentation for a struct field assignment.

Definition at line 61 of file FieldReference.cpp.

Public Member Functions

void AppendInstrumentation (const Automaton &, const TEquivalenceClass &)
 
std::string CompleteFieldName () const
 
Function * getTarget () const
 
 FieldInstrumentation (Function *InstrFn, Module &M, const StructType *T, const StringRef FieldName, size_t FieldIndex)
 

Constructor & Destructor Documentation

tesla::FieldInstrumentation::FieldInstrumentation ( Function *  InstrFn,
Module &  M,
const StructType *  T,
const StringRef  FieldName,
size_t  FieldIndex 
)
inline

Definition at line 71 of file FieldReference.cpp.

73  : InstrFn(InstrFn), Exit(FindBlock("exit", *InstrFn)), M(M),
74  StructTy(T), FieldName(FieldName)
75  {
76  }

Member Function Documentation

void tesla::FieldInstrumentation::AppendInstrumentation ( const Automaton A,
const TEquivalenceClass Trans 
)

Definition at line 292 of file FieldReference.cpp.

References tesla::ConstructKey(), tesla::ConstructTransitions(), tesla::AutomatonDescription::context, tesla::debug, tesla::FindStateUpdateFn(), tesla::Automaton::getAssertion(), tesla::Automaton::ID(), tesla::Automaton::Name(), tesla::panic(), tesla::Automaton::String(), and tesla::TeslaContext().

293  {
294 
295  debug << "AppendInstrumentation\n";
296 
297  LLVMContext& Ctx = InstrFn->getContext();
298  auto *Head = dyn_cast<FieldAssignTransition>(*Trans.begin());
299  assert(Head);
300  auto& Protobuf = Head->Assignment();
301 
302  // The instrumentation function should be passed three parameters:
303  // the struct, the new value and a pointer to the field.
304  auto& Params = InstrFn->getArgumentList();
305  assert(Params.size() == 3);
306 
307  auto i = Params.begin();
308  llvm::Argument *Struct = &*i++;
309  llvm::Argument *NewValue = &*i++;
310  llvm::Argument *FieldPtr = &*i++;
311 
312  // We will definitely pass the structure's address to tesla_update_state().
313  // We may also pass the new value, if it's e.g. a pointer: see below.
314  SmallVector<Value*,2> KeyValues;
315  KeyValues.push_back(Struct);
316 
317  // Insert new instrumention before the current "end" block for the automaton.
318  auto *End = NextInstrBlock(&A);
319  auto *Instr = BasicBlock::Create(Ctx, Head->ShortLabel(), InstrFn, End);
320  End->replaceAllUsesWith(Instr);
321  IRBuilder<> Builder(Instr);
322 
323  // Are we assigning a constant value (in which case we should try to match
324  // it against a protobuf-supplied pattern) or a variable (in which case we
325  // should add it to the struct tesla_key)?
326  auto& ExpectedAssignment = Protobuf.value();
327 
328  switch (ExpectedAssignment.type()) {
329  case Argument::Constant: {
330  // Match the new value against the expected value or else ignore it.
331  IntegerType *ValueType = dyn_cast<IntegerType>(NewValue->getType());
332  if (!ValueType)
333  panic("NewValue not an integer type");
334 
335  auto *Match = BasicBlock::Create(Ctx, "match: " + Head->ShortLabel(),
336  InstrFn, Instr);
337  Instr->replaceAllUsesWith(Match);
338  IRBuilder<> Matcher(Match);
339 
340  auto *Const = ConstantInt::getSigned(ValueType, ExpectedAssignment.value());
341  Value *Expected;
342 
343  switch (Protobuf.operation()) {
345  Expected = Const;
346  break;
347 
348  case FieldAssignment::PlusEqual:
349  Expected = Matcher.CreateAdd(Matcher.CreateLoad(FieldPtr), Const);
350  break;
351 
353  Expected = Matcher.CreateSub(Matcher.CreateLoad(FieldPtr), Const);
354  break;
355  }
356 
357  Matcher.CreateCondBr(Matcher.CreateICmpNE(NewValue, Expected), End, Instr);
358  break;
359  }
360 
361  case Argument::Variable:
362  KeyValues.push_back(NewValue);
363  break;
364 
365  case Argument::Any:
366  panic("'ANY' value should never be passed to struct field instrumentation");
367 
368  case Argument::Indirect:
369  panic("struct field instrumentation should not be passed indirect value");
370 
371  case Argument::Field:
372  panic("struct field instrumentation should not be passed struct field");
373  }
374 
375  Type* IntType = Type::getInt32Ty(Ctx);
376 
377  std::vector<Value*> Args;
378  Args.push_back(TeslaContext(A.getAssertion().context(), Ctx));
379  Args.push_back(ConstantInt::get(IntType, A.ID()));
380  Args.push_back(ConstructKey(Builder, M, KeyValues));
381  Args.push_back(Builder.CreateGlobalStringPtr(A.Name()));
382  Args.push_back(Builder.CreateGlobalStringPtr(A.String()));
383  Args.push_back(ConstructTransitions(Builder, M, Trans));
384 
385  Function *UpdateStateFn = FindStateUpdateFn(M, IntType);
386  assert(Args.size() == UpdateStateFn->arg_size());
387  Builder.CreateCall(UpdateStateFn, Args);
388  Builder.CreateBr(Exit);
389 }

+ Here is the call graph for this function:

std::string tesla::FieldInstrumentation::CompleteFieldName ( ) const
inline

Definition at line 65 of file FieldReference.cpp.

65  {
66  return (StructTy->getName() + "." + FieldName).str();
67  }
Function* tesla::FieldInstrumentation::getTarget ( ) const
inline

Definition at line 69 of file FieldReference.cpp.

69 { return InstrFn; }

The documentation for this class was generated from the following file: