Пример #1
0
static void printInst(const llvm::MCInst& inst) {
	const llvm::MCInstrDesc& id = MII->get(inst.getOpcode());
	llvm::outs() << MII->getName(inst.getOpcode()) << " (" << inst.getNumOperands() << ") ";

	for (int iop = 0; iop < inst.getNumOperands(); ++iop) {
		const llvm::MCOperand& op = inst.getOperand(iop);

		if (op.isReg()) {
			unsigned reg = op.getReg();
			const char* rcName;
			char clsn[128];

			if (id.OpInfo[iop].RegClass < MRI->getNumRegClasses()) {
				const llvm::MCRegisterClass& rc = MRI->getRegClass(id.OpInfo[iop].RegClass);
				rcName = rc.getName();
			} else {
				snprintf(clsn, sizeof(clsn), "CLS%d", id.OpInfo[iop].RegClass);
				rcName = clsn;
			}
			llvm::outs() << MRI->getName(reg) << "(" << rcName << ", " << (uint64_t)id.OpInfo[iop].OperandType << ")";
		} else if (op.isImm()) {
			llvm::outs() << op.getImm() << "(" << (uint64_t)id.OpInfo[iop].OperandType << ")";
		} else {
			llvm::outs() << "<UNK>";
		}

		llvm::outs() << ", ";
	}

	llvm::outs() << "\n";
}
Пример #2
0
// Convert the given assembly instruction into an inline ASM operation in lieu
// of decompiling it. The output instruction will look something like this
// (although note that i128 doesn't work properly with LLVM codegen for the
// inline ASM instructions, necessitating a vector instead).
// %151 = load i128, i128* %XMM0_read
// %152 = bitcast i128 %151 to <16 x i8>
// %153 = load i128, i128* %XMM1_read
// %154 = bitcast i128 %153 to <16 x i8>
// %AESDECrr = call <16 x i8> asm "\09aesdec\09%xmm1, %xmm0", "={XMM0},{XMM0},{XMM1}"(<16 x i8> %152, <16 x i8> %154)
// %155 = bitcast <16 x i8> %AESDECrr to i128
// store volatile i128 %155, i128* %XMM0_write
void ArchBuildInlineAsm(llvm::MCInst &inst, llvm::BasicBlock *block) {
  auto opcode = inst.getOpcode();

  // Use the printer to build the ASM string. We'll need to escape the $ in
  // register names with $$.
  std::stringstream asmString;
  {
    std::string outS;
    llvm::raw_string_ostream strOut(outS);
    gIP->printInst(&inst, strOut, "", *gSTI);
    for (char c : strOut.str()) {
      if (c == '$')
        asmString << "$$";
      else
        asmString << c;
    }
  }

  // Next, find all the registers being used as definitions or uses in the
  // inline ASM. This will write up the constraints for us, as well as
  // provide us with a list of types (for the inline ASM output) and a list of
  // values to pass into the string.
  llvm::SmallVector<llvm::Value *, 3> operands;
  llvm::SmallVector<llvm::Type *, 3> resultTypes;
  std::stringstream constraints;
  for (unsigned i = 0; i < inst.getNumOperands(); i++) {
    llvm::MCOperand &op = inst.getOperand(i);
    if (op.isReg()) {
      unsigned regSize = ArchRegisterSize(op.getReg());
      if (constraints.tellp() > 0) constraints << ",";
      if (i < gMII->get(opcode).getNumDefs()) {
        constraints << "=";

        if (regSize > 64) {
          // LLVM can't handle register constraints of i128, so we
          // need to map this to <16 x i8>.
          resultTypes.push_back(llvm::VectorType::get(
            llvm::Type::getInt8Ty(block->getContext()), regSize / 8));
        } else {
          resultTypes.push_back(llvm::IntegerType::get(block->getContext(),
            regSize));
        }
      } else {
        auto readReg = GENERIC_MC_READREG(block, op.getReg(), regSize);
        if (regSize > 64) {
          // LLVM can't handle register constraints of i128, so we
          // need to map this to <16 x i8>.
          readReg = llvm::CastInst::Create(llvm::Instruction::BitCast, readReg,
            llvm::VectorType::get(llvm::Type::getInt8Ty(block->getContext()), regSize / 8),
            "", block);
        }
        operands.push_back(readReg);
      }
      constraints << "{" << gMRI->getName(op.getReg()) << "}";
    }
  }

  // With all of these pieces, piece together the actual call to the inline ASM
  // string.
  llvm::SmallVector<llvm::Type *, 3> argTypes;
  for (auto val : operands)
    argTypes.push_back(val->getType());

  llvm::Type *returnTy;
  if (resultTypes.empty())
    returnTy = llvm::Type::getVoidTy(block->getContext());
  else if (resultTypes.size() == 1)
    returnTy = resultTypes[0];
  else
    returnTy = llvm::StructType::get(block->getContext(), resultTypes);

  auto asmTy = llvm::FunctionType::get(returnTy, argTypes, false);
  auto callee = llvm::InlineAsm::get(asmTy, asmString.str(), constraints.str(),
      false);
  llvm::Value *resultPack =
    llvm::CallInst::Create(callee, operands, "", block);

  // Unpack the called registers into the LLVM values.
  for (unsigned i = 0; i < resultTypes.size(); i++) {
    llvm::Value *result = resultTypes.size() == 1 ? resultPack :
      llvm::ExtractValueInst::Create(resultPack, i, "", block);
    llvm::Type *ty = resultTypes[i];
    // Cast vector outputs to iXYZ for R_WRITE.
    if (ty->isVectorTy()) {
      ty = llvm::Type::getIntNTy(block->getContext(),
        ty->getVectorNumElements() * 8);
      result = llvm::CastInst::Create(llvm::Instruction::BitCast, result,
        ty, "", block);
    }
    unsigned regNo = inst.getOperand(i).getReg();
    GENERIC_MC_WRITEREG(block, regNo, result);
  }
}