Skip to content

Commit aa607a0

Browse files
committedFeb 15, 2017
Name locally allocated variables by their real name.
If an array is allocated locally in a function (rather than globally or passed via function arguments), LLVM may emit IR that does not use the original source name, as in: float elems[4]; becomes: %13 = alloca float, i64 %12, align 16, !dbg !1416 tail call void @llvm.dbg.declare(metadata !{float* %13}, metadata !495), !dbg !1416 Originally, the variable could only be identified by the slot number 13, but the actual name (elems) is stored in debug information. This patch will identify this case, search for the debug declare call, extract the name of the variable, and store it for future usage. In the past, a load from elems would generate the following output for a GEP in the dynamic trace: 0,54,func_name,43,50,29,824880 2,64,0,1,indvars.iv, 1,64,140727758711584,1,13, r,64,140727758711584,1,50, And now, the third line becomes: 1,64,140727758711584,1,elems, Change-Id: I07e8ddc3f12cdaeeee6a3d41e8a39816eab8fa57
1 parent 8ebeea4 commit aa607a0

File tree

2 files changed

+69
-8
lines changed

2 files changed

+69
-8
lines changed
 

‎full-trace/full_trace.cpp

+46-6
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ bool Tracer::runOnBasicBlock(BasicBlock &BB) {
193193
st->purgeFunction();
194194
st->incorporateFunction(func);
195195
curr_function = func;
196+
slotToVarName.clear();
196197
}
197198

198199
if (!is_toplevel_mode && !is_tracking_function(funcName))
@@ -247,6 +248,10 @@ bool Tracer::runOnBasicBlock(BasicBlock &BB) {
247248
if (!itr->getType()->isVoidTy()) {
248249
handleInstructionResult(itr, nextitr, &env);
249250
}
251+
252+
if (isa<AllocaInst>(itr)) {
253+
processAllocaInstruction(itr);
254+
}
250255
}
251256
return false;
252257
}
@@ -410,18 +415,21 @@ bool Tracer::setOperandNameAndReg(Instruction *I, InstOperandParams *params) {
410415
}
411416

412417
bool Tracer::getInstId(Instruction *I, char *bbid, char *instid, int *instc) {
413-
int id = st->getLocalSlot(I);
414-
bool has_name = I->hasName();
415418
assert(instid != nullptr);
416-
if (has_name) {
417-
strcpy(instid, (char *)I->getName().str().c_str());
419+
if (I->hasName()) {
420+
strcpy(instid, I->getName().str().c_str());
418421
return true;
419422
}
420-
if (!has_name && id >= 0) {
423+
int id = st->getLocalSlot(I);
424+
if (slotToVarName.find(id) != slotToVarName.end()) {
425+
strcpy(instid, slotToVarName[id].c_str());
426+
return true;
427+
}
428+
if (id >= 0) {
421429
sprintf(instid, "%d", id);
422430
return true;
423431
}
424-
if (!has_name && id == -1) {
432+
if (id == -1) {
425433
// This instruction does not produce a value in a new register.
426434
// Examples include branches, stores, calls, returns.
427435
// instid is constructed using the bbid and a monotonically increasing
@@ -434,6 +442,38 @@ bool Tracer::getInstId(Instruction *I, char *bbid, char *instid, int *instc) {
434442
return false;
435443
}
436444

445+
void Tracer::processAllocaInstruction(BasicBlock::iterator it) {
446+
AllocaInst *alloca = dyn_cast<AllocaInst>(it);
447+
// If this instruction's output register is already named, then we don't need
448+
// to do any more searching.
449+
if (!alloca->hasName()) {
450+
int alloca_id = st->getLocalSlot(alloca);
451+
bool found_debug_declare = false;
452+
// The debug declare call is not guaranteed to come right after the alloca.
453+
while (!found_debug_declare && !it->isTerminator()) {
454+
it++;
455+
Instruction *I = it;
456+
DbgDeclareInst *di = dyn_cast<DbgDeclareInst>(I);
457+
if (di) {
458+
Value *wrapping_arg = di->getAddress();
459+
int id = st->getLocalSlot(wrapping_arg);
460+
// Ensure we've found the RIGHT debug declare call by comparing the
461+
// variable whose debug information is being declared with the variable
462+
// we're looking for.
463+
if (id != alloca_id)
464+
continue;
465+
466+
MDNode *md = di->getVariable();
467+
// The name of the variable is the third operand of the metadata node.
468+
Value *name_operand = md->getOperand(2);
469+
std::string name = name_operand->getName().str();
470+
slotToVarName[id] = name;
471+
found_debug_declare = true;
472+
}
473+
}
474+
}
475+
}
476+
437477
void Tracer::getBBId(Value *BB, char *bbid) {
438478
int id;
439479
id = st->getLocalSlot(BB);

‎full-trace/full_trace.h

+23-2
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ class Tracer : public BasicBlockPass {
130130
//
131131
// If the instruction does not produce a value, an artificial ID is
132132
// constructed by concatenating the given bbid, which both must not be NULL
133-
// and the current instc.
133+
// and the current instc, and this function returns false.
134134
//
135-
// The ID is returned as a string in instid.
135+
// The ID is stored in instid.
136136
bool getInstId(Instruction *I, char *bbid, char *instid, int *instc);
137137

138138
// Construct an ID using the given instruction and environment.
@@ -141,6 +141,17 @@ class Tracer : public BasicBlockPass {
141141
// Get and set the operand name for this instruction.
142142
bool setOperandNameAndReg(Instruction *I, InstOperandParams *params);
143143

144+
// Get the variable name for this locally allocated variable.
145+
//
146+
// An alloca instruction allocates a certain amount of memory on the stack.
147+
// This instruction will name the register that stores the pointer
148+
// with the original source name if it is not locally allocated on the
149+
// stack. If it is a local variable, it may just store it to a temporary
150+
// register and name it with a slot number. In this latter case, track down
151+
// the original variable name using debug information and store it in the
152+
// slotToVarName map.
153+
void processAllocaInstruction(BasicBlock::iterator it);
154+
144155
// Construct an ID for the given basic block.
145156
//
146157
// This ID is either the name of the basic block (e.g. ".lr.ph",
@@ -170,6 +181,16 @@ class Tracer : public BasicBlockPass {
170181
// True if WORKLOAD specifies a single function, in which case the tracer
171182
// will track all functions called by it (the top-level function).
172183
bool is_toplevel_mode;
184+
185+
private:
186+
// Stores names of local variables allocated by alloca.
187+
//
188+
// For alloca instructions that allocate local memory, this maps the
189+
// register name (aka slot number) to the name of the variable itself.
190+
//
191+
// Since slot numbers are reused across functions, this has to be cleared
192+
// when we switch to a new function.
193+
std::map<unsigned, std::string> slotToVarName;
173194
};
174195

175196
/* Reads a labelmap file and inserts it into the dynamic trace.

0 commit comments

Comments
 (0)
Please sign in to comment.