282 const llvm::MachineInstr& mi,
283 const std::map<std::string, unsigned>& symbolTable,
284 const llvm::Mangler& mangler) {
287 assert(mi.isInlineAsm() &&
"MI must hold inline asm.");
288 std::string result = mi.getOperand(
289 InlineAsm::MIOp_AsmString).getSymbolName();
295 auto mangledNameFn = [&mangler](
const GlobalValue* gv) -> std::string {
296 SmallString<256> Buffer;
297 mangler.getNameWithPrefix(Buffer, gv,
false);
298 std::string name(Buffer.c_str());
304 std::map<std::string, std::string> templateStringMap;
306 const std::string tmplPrefix =
"$";
307 std::string unhandledKind;
309 for (
auto& asmOpd : opdMap) {
310 unsigned asmOpdPos = asmOpd.first;
311 unsigned asmOpdKind = std::get<0>(asmOpd.second);
312 std::vector<const llvm::MachineOperand*>& flagOpds =
313 std::get<1>(asmOpd.second);
314 unsigned numAsmOpds = flagOpds.size();
315 switch (asmOpdKind) {
316 case InlineAsm::Kind_Mem:
317 if (unhandledKind.empty()) unhandledKind =
"mem";
320 if (unhandledKind.empty()) unhandledKind =
"??";
322 std::cerr <<
"substituteAsmString():"
323 <<
" Ignoring asm operand kind: "
324 << unhandledKind << std::endl;
326 unhandledKind.clear();
329 case InlineAsm::Kind_RegDefEarlyClobber:
330 case InlineAsm::Kind_RegDef:
331 case InlineAsm::Kind_RegUse:
333 templateStringMap.insert(std::make_pair(
334 tmplPrefix + std::to_string(asmOpdPos),
338 case InlineAsm::Kind_Imm:
340 if (flagOpds.at(0)->isImm()) {
341 templateStringMap.insert(std::make_pair(
342 tmplPrefix + std::to_string(asmOpdPos),
343 std::to_string(flagOpds.at(0)->getImm())));
344 }
else if (flagOpds.at(0)->isGlobal()) {
345 std::string name = mangledNameFn(flagOpds.at(0)->getGlobal());
346 unsigned address = 0;
347 if (symbolTable.find(name) != symbolTable.end()) {
348 address = symbolTable.at(name)
349 + flagOpds.at(0)->getOffset();
355 "Could not determine address of symbol '"
356 + name +
"'. \nNote: Functions as inline asm "
357 "operands are not supported.");
360 templateStringMap.insert(std::make_pair(
361 tmplPrefix + std::to_string(asmOpdPos),
362 std::to_string(address)));
367 case InlineAsm::Kind_Clobber:
374 auto findTemplateStrFn = [](
const std::string& str,
size_t pos)
375 -> std::tuple<size_t, size_t> {
376 if (pos > str.size()) {
377 return std::make_tuple(std::string::npos, 0);
380 while ((pos = str.find(
"$", pos)) != std::string::npos) {
381 size_t endPos = str.find_first_not_of(
"0123456789", pos+1);
382 if (endPos == std::string::npos) {
384 if (str.size()-pos > 1) {
385 return std::make_tuple(pos, str.size()-pos);
387 pos = std::string::npos;
394 return std::make_tuple(pos, len);
399 std::set<std::string> replacedTemplStrs;
401 std::tie(pos, len) = findTemplateStrFn(result, pos);
402 if (pos == std::string::npos)
break;
403 const std::string& templStr = result.substr(pos, len);
404 replacedTemplStrs.insert(templStr);
405 result.replace(pos, len, templateStringMap.at(templStr));
411 for (
auto& tmplStrPair : templateStringMap) {
412 const std::string& tmplStr = tmplStrPair.first;
413 if (replacedTemplStrs.count(tmplStr))
continue;
417 msg = std::to_string(opdIdx) +
". operand is unreferenced";
419 msg =
"There is unreferenced operand";
425 if (!srcFile.empty()) {
426 srcLoc = srcFile +
":" + std::to_string(srcLine) +
": ";
428 std::cerr << srcLoc <<
"Warning: " << msg
429 <<
" in an inline asm block."
434 std::string uidTmplStr =
"${:uid}";
435 auto uid = std::to_string(
asmId_++);
437 while ((pos = result.find(uidTmplStr, pos)) != std::string::npos) {
438 result.replace(pos, uidTmplStr.size(), uid);
513 &&
"Procedures are not allowed in non-file-level inline asm.");
516 std::map<const TTAProgram::Instruction*, TTAProgram::Instruction*>
518 for (
decltype(procCount) i = 0; i < procCount; i++) {
521 for (
decltype(instrCount) i = 0; i < instrCount; i++) {
522 const auto& oldInstr = proc.instructionAtIndex(i);
523 auto newInstr = oldInstr.copy();
524 targetBB.
add(newInstr);
525 instrCopyMap.insert({&oldInstr, newInstr});
529 for (
auto& pair : instrCopyMap) {
530 auto& newInstr = *pair.second;
532 auto& oldRefInstr = refTerm->instructionReference().instruction();
533 assert(instrCopyMap.count(&oldRefInstr));
534 auto newRefInstr = instrCopyMap.at(&oldRefInstr);
536 refTerm->setInstructionReference(newRef);