60 #include <llvm/CodeGen/MachineOperand.h>
61 #include <llvm/CodeGen/MachineInstr.h>
62 #include "llvm/IR/InlineAsm.h"
63 #include "llvm/IR/Mangler.h"
64 #include <llvm/ADT/SmallString.h>
70 const llvm::Mangler& mangler) :
71 tm_(tm), mangler_(mangler) {
88 const llvm::MachineInstr& inlineAsmMI,
89 const std::map<std::string, unsigned>& symbolTable,
93 #ifdef DEBUG_INLINE_ASM_PARSER
94 std::cerr <<
"*** before position string substitution:" << std::endl;
95 inlineAsmMI.print(llvm::dbgs());
101 #ifdef DEBUG_INLINE_ASM_PARSER
102 std::cerr <<
"*** before inline asm parsing:" << std::endl
103 << asmString << std::endl;
114 if (!parser.
compile(asmString)) {
116 parser.
errorLine(),
"Syntax error in inline assembly.");
129 std::unique_ptr<TTAProgram::Program> prog;
133 prog.reset(tpefFactory.
build());
147 #ifdef DEBUG_INLINE_ASM_PARSER
148 std::cerr <<
"*** After inline asm parsing:" << std::endl
160 const MachineInstr& mi,
167 std::string sourceFileName;
168 size_t sourceLineNumber;
171 if (sourceFileName.size() >
174 sourceFileName.substr(
175 sourceFileName.size() -
182 if (sourceFileName.empty()) sourceFileName =
"???";
189 for (
int m = 0; m < instr.
moveCount(); m++) {
206 const llvm::MachineInstr& mi,
215 for (
auto& opds : asmOperandMap) {
216 auto asmOpdKind = std::get<0>(opds.second);
217 auto& asmOpdNodes = std::get<1>(opds.second);
219 switch (asmOpdKind) {
222 case InlineAsm::Kind_RegUse:
223 assert(asmOpdNodes.size() == 1);
225 liveRangeData.inlineAsmRegUses_.insert(reg);
227 case InlineAsm::Kind_RegDefEarlyClobber:
228 case InlineAsm::Kind_RegDef:
229 assert(asmOpdNodes.size() == 1);
231 liveRangeData.inlineAsmRegDefs_.insert(reg);
233 case InlineAsm::Kind_Clobber:
234 assert(asmOpdNodes.size() == 1);
236 liveRangeData.inlineAsmClobbers_.insert(reg);
252 const llvm::MachineInstr&,
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);
451 if (mi.isInlineAsm()) {
453 mi.getOperand(InlineAsm::MIOp_AsmString).getSymbolName());
454 return amsStr.find_first_of(
"->;") != std::string::npos;
472 std::vector<TTAProgram::TerminalInstructionReference*>
477 std::vector<TTAProgram::TerminalInstructionReference*> result;
479 for (
int i = 0; i < instr.
moveCount(); i++) {
480 auto& move = instr.
move(i);
481 auto& srcTerml = move.
source();
482 if (srcTerml.isInstructionAddress()) {
483 assert(
dynamic_cast<TerminalInstructionReference*
>(&srcTerml));
484 result.push_back(
static_cast<TerminalInstructionReference*
>(
491 if (valTerml.isInstructionAddress()) {
492 assert(
dynamic_cast<TerminalInstructionReference*
>(&valTerml));
493 result.push_back(
static_cast<TerminalInstructionReference*
>(
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);