45 #include "llvm/IR/Function.h"
46 #include "llvm/IR/Instructions.h"
47 #include "llvm/IR/Module.h"
48 #include "llvm/Support/raw_ostream.h"
60 char AssertionSiteInstrumenter::ID = 0;
62 AssertionSiteInstrumenter::~AssertionSiteInstrumenter() {
63 ::google::protobuf::ShutdownProtobufLibrary();
66 bool AssertionSiteInstrumenter::runOnModule(Module &M) {
73 set<CallInst*> AssertCalls;
74 for (
auto I = AssertFn->use_begin(); I != AssertFn->use_end(); ++I)
75 AssertCalls.insert(cast<CallInst>(*I));
77 return ConvertAssertions(AssertCalls, M);
81 bool AssertionSiteInstrumenter::ConvertAssertions(
82 set<CallInst*>& AssertCalls, Module& Mod) {
88 for (
auto *Assert : AssertCalls) {
90 IRBuilder<> Builder(Assert);
93 ParseAssertionLocation(&Loc, Assert);
95 auto *A = M.FindAutomaton(Loc);
102 for (
auto EquivClass : *A) {
103 auto *Head = *EquivClass.begin();
110 +
"' contains NOW event with location '"
113 if (!(InstrFn = CreateInstrumentation(*A, EquivClass, Mod)))
114 panic(
"error instrumenting NOW event");
120 panic(
"automaton '" +
ShortName(Loc) +
"' contains no NOW event");
124 std::map<string,Value*> ValuesInScope;
125 BasicBlock *Block = Assert->getParent();
126 Function *Fn = Block->getParent();
128 for (llvm::Argument& A : Fn->getArgumentList())
129 ValuesInScope[A.getName()] = &A;
132 for (Instruction& I : B) {
136 if (StoreInst *Store = dyn_cast<StoreInst>(&I)) {
137 Value *V = Store->getPointerOperand();
139 ValuesInScope[V->getName()] = V;
144 const AutomatonDescription& Descrip = A->getAssertion();
145 size_t ArgCount = Descrip.argument_size();
146 assert(ArgCount == InstrFn->getArgumentList().size());
148 std::vector<Value*> Args(ArgCount, NULL);
149 for (
const Argument& Arg : Descrip.argument()) {
150 Value *V = ValuesInScope[Arg.name()];
152 panic(
"assertion references non-existent variable '" + Arg.name()
153 +
"'; was it defined under '#ifdef TESLA'?");
159 for (
auto i = V->use_begin(); i != V->use_end(); i++) {
160 auto *Store = dyn_cast<StoreInst>(*i);
164 Ptr = Store->getPointerOperand();
166 if (V == Store->getValueOperand())
167 assert(isa<AllocaInst>(Ptr));
175 Value *Val = Builder.CreateLoad(Ptr,
"intrumentation_" + Arg.name());
176 Args[Arg.index()] =
Cast(Val, Arg.name(), IntPtrTy, Builder);
179 Builder.CreateCall(InstrFn, Args);
182 Assert->removeFromParent();
187 AssertFn->removeFromParent();
194 Function* AssertionSiteInstrumenter::CreateInstrumentation(
197 const AutomatonDescription& Descrip = A.getAssertion();
198 LLVMContext& Ctx = M.getContext();
200 const size_t ArgCount = Descrip.argument_size();
202 Type *Void = Type::getVoidTy(Ctx);
206 std::vector<Type*> ArgTypes(ArgCount, IntPtrTy);
207 FunctionType *FnType = FunctionType::get(Void, ArgTypes,
false);
210 Function *InstrFn = dyn_cast<Function>(M.getOrInsertFunction(Name, FnType));
211 assert(InstrFn != NULL &&
"instrumentation function not a Function!");
213 string Message = (
"[NOW] automaton " + Twine(A.ID())).str();
217 IRBuilder<> Builder(Instr);
219 Type *IntType = Type::getInt32Ty(Ctx);
223 std::vector<Value*> InstrArgs;
224 for (Value& Arg : InstrFn->getArgumentList()) InstrArgs.push_back(&Arg);
226 std::vector<Value*> Args;
227 Args.push_back(
TeslaContext(A.getAssertion().context(), Ctx));
228 Args.push_back(ConstantInt::get(IntType, A.ID()));
230 Args.push_back(Builder.CreateGlobalStringPtr(A.Name()));
231 Args.push_back(Builder.CreateGlobalStringPtr(A.String()));
235 assert(Args.size() == UpdateStateFn->arg_size());
236 Builder.CreateCall(UpdateStateFn, Args);
238 auto Exit = BasicBlock::Create(Ctx,
"exit", InstrFn);
239 IRBuilder<>(Exit).CreateRetVoid();
241 Builder.CreateBr(Exit);
247 void AssertionSiteInstrumenter::ParseAssertionLocation(
248 Location *Loc, CallInst *Call) {
252 if (Call->getNumArgOperands() < 3)
253 panic(
"TESLA assertion must have at least 3 arguments");
256 GlobalVariable *NameVar =
257 dyn_cast<GlobalVariable>(Call->getOperand(0)->stripPointerCasts());
259 ConstantDataArray *A;
261 !(A = dyn_cast_or_null<ConstantDataArray>(NameVar->getInitializer()))) {
263 panic(
"unable to parse filename from TESLA assertion");
266 *Loc->mutable_filename() = A->getAsString();
270 ConstantInt *Line = dyn_cast<ConstantInt>(Call->getOperand(1));
272 Call->getOperand(1)->dump();
273 panic(
"assertion line must be a constant int");
276 Loc->set_line(Line->getLimitedValue(INT_MAX));
278 ConstantInt *Count = dyn_cast<ConstantInt>(Call->getOperand(2));
280 Call->getOperand(2)->dump();
281 panic(
"assertion count must be a constant int");
284 Loc->set_counter(Count->getLimitedValue(INT_MAX));