39 #include <llvm/ADT/StringMap.h>
40 #include <llvm/IR/Constants.h>
41 #include <llvm/IR/Instructions.h>
42 #include <llvm/IR/Module.h>
43 #include <llvm/Support/raw_ostream.h>
56 char FieldReferenceInstrumenter::ID = 0;
57 raw_ostream&
debug =
debugs(
"tesla.instrumentation.field_assign");
66 return (StructTy->getName() +
"." + FieldName).str();
72 const StringRef FieldName,
size_t FieldIndex)
73 : InstrFn(InstrFn), Exit(
FindBlock(
"exit", *InstrFn)), M(M),
74 StructTy(T), FieldName(FieldName)
79 BasicBlock* NextInstrBlock(
const Automaton*);
84 const StructType *StructTy;
85 const StringRef FieldName;
87 map<const Automaton*,BasicBlock*> NextInstr;
91 FieldReferenceInstrumenter::~FieldReferenceInstrumenter() {
92 for (
auto& i : Instrumentation)
97 bool FieldReferenceInstrumenter::runOnModule(Module &Mod) {
99 <<
"===================================================================\n"
100 << __PRETTY_FUNCTION__ <<
"\n"
101 <<
"-------------------------------------------------------------------\n"
102 <<
"module: " << Mod.getModuleIdentifier() <<
"\n";
109 for (
auto *Root : M.RootAutomata())
110 BuildInstrumentation(*M.FindAutomaton(Root->identifier()));
112 debug <<
"instrumentation:\n";
113 for (
auto& i : Instrumentation) {
114 debug <<
" " << i.getKey() <<
" -> ";
115 i.getValue()->getTarget()->getType()->print(
debug);
120 <<
"-------------------------------------------------------------------\n"
121 <<
"looking for field references...\n"
128 std::map<LoadInst*,FieldInstrumentation*> Loads;
129 std::map<StoreInst*,FieldInstrumentation*> Stores;
134 for (Function& Fn : Mod.getFunctionList()) {
138 for (
auto i = Fn.use_begin(); i != Fn.use_end(); i++) {
140 OwningPtr<PtrAnnotation> A(PtrAnnotation::Interpret(*i));
150 auto *Instr = Instrumentation[Name];
154 for (User *U : *Annotation) {
155 auto *
Cast = dyn_cast<CastInst>(U);
158 panic(
"annotation user not a bitcast",
false);
161 for (
auto k =
Cast->use_begin(); k !=
Cast->use_end(); k++) {
162 if (
auto *Load = dyn_cast<LoadInst>(*k))
163 Loads.insert(std::make_pair(Load, Instr));
165 else if (
auto *Store = dyn_cast<StoreInst>(*k))
166 Stores.insert(std::make_pair(Store, Instr));
170 panic(
"expected load or store with annotated value",
false);
178 InstrumentLoad(i.first, i.second);
180 for (
auto i : Stores)
181 InstrumentStore(i.first, i.second);
187 void FieldReferenceInstrumenter::BuildInstrumentation(
const Automaton& A) {
188 for (
auto& Transitions : A)
189 GetInstr(A, Transitions);
193 FieldInstrumentation* FieldReferenceInstrumenter::GetInstr(
196 auto *Head = dyn_cast<FieldAssignTransition>(*Trans.begin());
200 debug << Head->String() <<
"\n";
201 auto& Protobuf = Head->Assignment();
202 auto StructName = Protobuf.field().type();
203 auto FieldName = Protobuf.field().name();
204 string FullName = StructName +
"." + FieldName;
206 FieldInstrumentation *Instr;
208 auto Existing = Instrumentation.find(FullName);
209 if (Existing != Instrumentation.end())
210 Instr = Existing->second;
213 StructType *T = Mod->getTypeByName(
"struct." + StructName);
221 Instr =
new FieldInstrumentation(InstrFn, *Mod, T,
222 FieldName, Protobuf.field().index());
224 Instrumentation[FullName] = Instr;
227 Instr->AppendInstrumentation(A, Trans);
233 bool FieldReferenceInstrumenter::InstrumentLoad(
234 LoadInst*, FieldInstrumentation*) {
245 bool FieldReferenceInstrumenter::InstrumentStore(
246 StoreInst *Store, FieldInstrumentation *Instr) {
248 assert(Store != NULL);
249 assert(Instr != NULL);
251 debug <<
"instrumenting: ";
255 assert(Store->getNumOperands() > 1);
256 Value *Val = Store->getOperand(0);
257 Value *Ptr = Store->getOperand(1);
261 Value *StructPtr = NULL;
264 User *U = dyn_cast<User>(V);
267 debug <<
" is not a User!\n";
268 panic(
"expected a User");
271 assert(U->getNumOperands() > 0);
272 V = U->getOperand(0);
274 auto *PointerTy = dyn_cast<PointerType>(V->getType());
275 if (PointerTy && PointerTy->getElementType()->isStructTy())
278 }
while (StructPtr == NULL);
280 std::vector<Value*> Args;
281 Args.push_back(StructPtr);
285 IRBuilder<> Builder(Store);
286 Builder.CreateCall(Instr->getTarget(), Args);
292 void FieldInstrumentation::AppendInstrumentation(
295 debug <<
"AppendInstrumentation\n";
297 LLVMContext& Ctx = InstrFn->getContext();
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()) {
329 case Argument::Constant: {
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()) {
344 case FieldAssignment::SimpleAssign:
348 case FieldAssignment::PlusEqual:
349 Expected = Matcher.CreateAdd(Matcher.CreateLoad(FieldPtr), Const);
352 case FieldAssignment::MinusEqual:
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");
371 case Argument::Field:
372 panic(
"struct field instrumentation should not be passed struct field");
375 Type* IntType = Type::getInt32Ty(Ctx);
377 std::vector<Value*> Args;
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);
391 BasicBlock* FieldInstrumentation::NextInstrBlock(
const Automaton *A) {
392 auto Existing = NextInstr.find(A);
393 if (Existing != NextInstr.end())
394 return Existing->second;
396 auto& Ctx = M.getContext();
397 auto *Start = BasicBlock::Create(Ctx, A->
Name(), InstrFn, Exit);
398 auto *End = BasicBlock::Create(Ctx, A->
Name() +
":end", InstrFn, Exit);
400 Exit->replaceAllUsesWith(End);
402 IRBuilder<>(Start).CreateBr(End);
403 IRBuilder<>(End).CreateBr(Exit);