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"; }
bool EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn) { bool success = false; const uint32_t imm16 = insn.getOperand(2).getImm(); uint32_t imm = SignedBits(imm16, 15, 0); uint64_t result; uint32_t src, dst; dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); /* Check if this is addiu sp,<src>,imm16 */ if (dst == gcc_dwarf_sp_mips64) { /* read <src> register */ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success); if (!success) return false; result = src_opd_val + imm; Context context; RegisterInfo reg_info_sp; if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp)) context.SetRegisterPlusOffset (reg_info_sp, imm); /* We are allocating bytes on stack */ context.type = eContextAdjustStackPointer; WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result); } return true; }
bool EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn) { uint32_t src, base; src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src)) { RegisterValue data_src; RegisterInfo reg_info_src; if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src)) return false; Context context; context.type = eContextRegisterLoad; if (!WriteRegister (context, ®_info_src, data_src)) return false; return true; } return false; }
static std::string getLocalName(const llvm::MCInst& inst, unsigned iop) { const llvm::MCOperand& op = inst.getOperand(iop); if (op.isReg() && strcmp(MRI->getName(op.getReg()), "RBP") == 0) { char buf[128]; snprintf(buf, 128, "local_%x", -inst.getOperand(iop + 3).getImm()); return std::string(buf); } else { return std::string("UNK"); } }
bool EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn) { bool success = false; uint32_t imm16 = insn.getOperand(2).getImm(); uint32_t imm = SignedBits(imm16, 15, 0); uint32_t src, base; src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); /* We look for sp based non-volatile register stores */ if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src)) { uint32_t address; RegisterInfo reg_info_base; RegisterInfo reg_info_src; if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base) || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src)) return false; /* read SP */ address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success); if (!success) return false; /* destination address */ address = address + imm; Context context; RegisterValue data_src; context.type = eContextPushRegisterOnStack; context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; Error error; if (!ReadRegister (®_info_base, data_src)) return false; if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) return false; if (!WriteMemory (context, address, buffer, reg_info_src.byte_size)) return false; return true; } return false; }
static DecodeStatus DecodeSingleIndexedInstruction(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { unsigned Rt = fieldFromInstruction(Insn, 0, 5); unsigned Rn = fieldFromInstruction(Insn, 5, 5); unsigned Imm9 = fieldFromInstruction(Insn, 12, 9); unsigned Opc = fieldFromInstruction(Insn, 22, 2); unsigned V = fieldFromInstruction(Insn, 26, 1); unsigned Size = fieldFromInstruction(Insn, 30, 2); if (Opc == 0 || (V == 1 && Opc == 2)) { // It's a store, the MCInst gets: Rn_wb, Rt, Rn, Imm DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); } if (V == 0 && (Opc == 2 || Size == 3)) { DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder); } else if (V == 0) { DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder); } else if (V == 1 && (Opc & 2)) { DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder); } else { switch (Size) { case 0: DecodeFPR8RegisterClass(Inst, Rt, Address, Decoder); break; case 1: DecodeFPR16RegisterClass(Inst, Rt, Address, Decoder); break; case 2: DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder); break; case 3: DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder); break; } } if (Opc != 0 && (V != 1 || Opc != 2)) { // It's a load, the MCInst gets: Rt, Rn_wb, Rn, Imm DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); } DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); Inst.addOperand(MCOperand::CreateImm(Imm9)); // N.b. The official documentation says undpredictable if Rt == Rn, but this // takes place at the architectural rather than encoding level: // // "STR xzr, [sp], #4" is perfectly valid. if (V == 0 && Rt == Rn && Rn != 31) return MCDisassembler::SoftFail; else return MCDisassembler::Success; }
static DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler::Fail; uint16_t Register = getReg(Decoder, AArch64::GPR64RegClassID, RegNo); Inst.addOperand(MCOperand::CreateReg(Register)); return MCDisassembler::Success; }
static DecodeStatus DecodeFPZeroOperand(llvm::MCInst &Inst, unsigned RmBits, uint64_t Address, const void *Decoder) { // Any bits are valid in the instruction (they're architecturally ignored), // but a code generator should insert 0. Inst.addOperand(MCOperand::CreateImm(0)); return MCDisassembler::Success; }
DecodeStatus AMDGPUDisassembler::DecodeVGPR_32RegisterClass(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr) const { unsigned RegID; if (DecodeVgprRegister(Imm, RegID) == MCDisassembler::Success) { Inst.addOperand(MCOperand::createReg(RegID)); return MCDisassembler::Success; } return MCDisassembler::Fail; }
static DecodeStatus DecodeRegisterClassByID(llvm::MCInst &Inst, unsigned RegNo, unsigned RegID, const void *Decoder) { if (RegNo > 31) return MCDisassembler::Fail; uint16_t Register = getReg(Decoder, RegID, RegNo); Inst.addOperand(MCOperand::CreateReg(Register)); return MCDisassembler::Success; }
static DecodeStatus DecodeRegExtendOperand(llvm::MCInst &Inst, unsigned ShiftAmount, uint64_t Address, const void *Decoder) { // Only values 0-4 are valid for this 3-bit field if (ShiftAmount > 4) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(ShiftAmount)); return MCDisassembler::Success; }
static DecodeStatus DecodeLogicalImmOperand(llvm::MCInst &Inst, unsigned Bits, uint64_t Address, const void *Decoder) { uint64_t Imm; if (!A64Imms::isLogicalImmBits(RegWidth, Bits, Imm)) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(Bits)); return MCDisassembler::Success; }
static DecodeStatus DecodeCVT32FixedPosOperand(llvm::MCInst &Inst, unsigned Imm6Bits, uint64_t Address, const void *Decoder) { // 1 <= Imm <= 32. Encoded as 64 - Imm so: 63 >= Encoded >= 32. if (Imm6Bits < 32) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(Imm6Bits)); return MCDisassembler::Success; }
static DecodeStatus Decode32BitShiftOperand(llvm::MCInst &Inst, unsigned ShiftAmount, uint64_t Address, const void *Decoder) { // Only values below 32 are valid for a 32-bit register if (ShiftAmount > 31) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(ShiftAmount)); return MCDisassembler::Success; }
static DecodeStatus DecodeSysRegOperand(const A64SysReg::SysRegMapper &Mapper, llvm::MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { bool ValidNamed; Mapper.toString(Val, ValidNamed); Inst.addOperand(MCOperand::CreateImm(Val)); return ValidNamed ? MCDisassembler::Success : MCDisassembler::Fail; }
static DecodeStatus DecodeBitfield32ImmOperand(llvm::MCInst &Inst, unsigned Imm6Bits, uint64_t Address, const void *Decoder) { // In the 32-bit variant, bit 6 must be zero. I.e. the immediate must be // between 0 and 31. if (Imm6Bits > 31) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(Imm6Bits)); return MCDisassembler::Success; }
static DecodeStatus DecodeAddrRegExtendOperand(llvm::MCInst &Inst, unsigned OptionHiS, uint64_t Address, const void *Decoder) { // Option{1} must be 1. OptionHiS is made up of {Option{2}, Option{1}, // S}. Hence we want to check bit 1. if (!(OptionHiS & 2)) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(OptionHiS)); return MCDisassembler::Success; }
static DecodeStatus DecodeMoveWideImmOperand(llvm::MCInst &Inst, unsigned FullImm, uint64_t Address, const void *Decoder) { unsigned Imm16 = FullImm & 0xffff; unsigned Shift = FullImm >> 16; if (RegWidth == 32 && Shift > 1) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(Imm16)); Inst.addOperand(MCOperand::CreateImm(Shift)); return MCDisassembler::Success; }
static DecodeStatus DecodeNamedImmOperand(llvm::MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { SomeNamedImmMapper Mapper; bool ValidNamed; Mapper.toString(Val, ValidNamed); if (ValidNamed || Mapper.validImm(Val)) { Inst.addOperand(MCOperand::CreateImm(Val)); return MCDisassembler::Success; } return MCDisassembler::Fail; }
// Decodes the instruction, and returns the number of bytes decoded. size_t ArchDecodeInstruction(const uint8_t *bytes, const uint8_t *bytes_end, uintptr_t va, llvm::MCInst &inst) { size_t total_size = 0; size_t max_size = static_cast<size_t>(bytes_end - bytes); std::unordered_set<unsigned> prefixes; for (; total_size < max_size; ) { llvm::ArrayRef<uint8_t> bytes_to_decode( &(bytes[total_size]), max_size - total_size); uint64_t size = 0; auto decode_status = gDisassembler->getInstruction( inst, size, bytes_to_decode, va, llvm::nulls(), llvm::nulls()); if (llvm::MCDisassembler::Success != decode_status) { return 0; } total_size += size; switch (auto op_code = inst.getOpcode()) { case llvm::X86::CS_PREFIX: case llvm::X86::DATA16_PREFIX: case llvm::X86::DS_PREFIX: case llvm::X86::ES_PREFIX: case llvm::X86::FS_PREFIX: case llvm::X86::GS_PREFIX: case llvm::X86::LOCK_PREFIX: case llvm::X86::REPNE_PREFIX: case llvm::X86::REP_PREFIX: case llvm::X86::REX64_PREFIX: case llvm::X86::SS_PREFIX: case llvm::X86::XACQUIRE_PREFIX: case llvm::X86::XRELEASE_PREFIX: prefixes.insert(op_code); break; default: max_size = 0; // Stop decoding. break; } } FixupInstruction(inst, prefixes); return total_size; }
static DecodeStatus DecodeNeonMovImmShiftOperand(llvm::MCInst &Inst, unsigned ShiftAmount, uint64_t Address, const void *Decoder) { bool IsLSL = false; if (Ext == A64SE::LSL) IsLSL = true; else if (Ext != A64SE::MSL) return MCDisassembler::Fail; // MSL and LSLH accepts encoded shift amount 0 or 1. if ((!IsLSL || (IsLSL && IsHalf)) && ShiftAmount != 0 && ShiftAmount != 1) return MCDisassembler::Fail; // LSL accepts encoded shift amount 0, 1, 2 or 3. if (IsLSL && ShiftAmount > 3) return MCDisassembler::Fail; Inst.addOperand(MCOperand::CreateImm(ShiftAmount)); return MCDisassembler::Success; }
static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { // This decoder exists to add the dummy Lane operand to the MCInst, which must // be 1 in assembly but has no other real manifestation. unsigned Rd = fieldFromInstruction(Insn, 0, 5); unsigned Rn = fieldFromInstruction(Insn, 5, 5); unsigned IsToVec = fieldFromInstruction(Insn, 16, 1); if (IsToVec) { DecodeVPR128RegisterClass(Inst, Rd, Address, Decoder); DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder); } else { DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); DecodeVPR128RegisterClass(Inst, Rn, Address, Decoder); } // Add the lane Inst.addOperand(MCOperand::CreateImm(1)); return MCDisassembler::Success; }
static DecodeStatus DecodeBitfieldInstruction(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { unsigned Rd = fieldFromInstruction(Insn, 0, 5); unsigned Rn = fieldFromInstruction(Insn, 5, 5); unsigned ImmS = fieldFromInstruction(Insn, 10, 6); unsigned ImmR = fieldFromInstruction(Insn, 16, 6); unsigned SF = fieldFromInstruction(Insn, 31, 1); // Undef for 0b11 just in case it occurs. Don't want the compiler to optimise // out assertions that it thinks should never be hit. enum OpcTypes { SBFM = 0, BFM, UBFM, Undef } Opc; Opc = (OpcTypes)fieldFromInstruction(Insn, 29, 2); if (!SF) { // ImmR and ImmS must be between 0 and 31 for 32-bit instructions. if (ImmR > 31 || ImmS > 31) return MCDisassembler::Fail; } if (SF) { DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); // BFM MCInsts use Rd as a source too. if (Opc == BFM) DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder); } else { DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder); // BFM MCInsts use Rd as a source too. if (Opc == BFM) DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder); DecodeGPR32RegisterClass(Inst, Rn, Address, Decoder); } // ASR and LSR have more specific patterns so they won't get here: assert(!(ImmS == 31 && !SF && Opc != BFM) && "shift should have used auto decode"); assert(!(ImmS == 63 && SF && Opc != BFM) && "shift should have used auto decode"); // Extension instructions similarly: if (Opc == SBFM && ImmR == 0) { assert((ImmS != 7 && ImmS != 15) && "extension got here"); assert((ImmS != 31 || SF == 0) && "extension got here"); } else if (Opc == UBFM && ImmR == 0) { assert((SF != 0 || (ImmS != 7 && ImmS != 15)) && "extension got here"); } if (Opc == UBFM) { // It might be a LSL instruction, which actually takes the shift amount // itself as an MCInst operand. if (SF && (ImmS + 1) % 64 == ImmR) { Inst.setOpcode(AArch64::LSLxxi); Inst.addOperand(MCOperand::CreateImm(63 - ImmS)); return MCDisassembler::Success; } else if (!SF && (ImmS + 1) % 32 == ImmR) { Inst.setOpcode(AArch64::LSLwwi); Inst.addOperand(MCOperand::CreateImm(31 - ImmS)); return MCDisassembler::Success; } } // Otherwise it's definitely either an extract or an insert depending on which // of ImmR or ImmS is larger. unsigned ExtractOp, InsertOp; switch (Opc) { default: llvm_unreachable("unexpected instruction trying to decode bitfield"); case SBFM: ExtractOp = SF ? AArch64::SBFXxxii : AArch64::SBFXwwii; InsertOp = SF ? AArch64::SBFIZxxii : AArch64::SBFIZwwii; break; case BFM: ExtractOp = SF ? AArch64::BFXILxxii : AArch64::BFXILwwii; InsertOp = SF ? AArch64::BFIxxii : AArch64::BFIwwii; break; case UBFM: ExtractOp = SF ? AArch64::UBFXxxii : AArch64::UBFXwwii; InsertOp = SF ? AArch64::UBFIZxxii : AArch64::UBFIZwwii; break; } // Otherwise it's a boring insert or extract Inst.addOperand(MCOperand::CreateImm(ImmR)); Inst.addOperand(MCOperand::CreateImm(ImmS)); if (ImmS < ImmR) Inst.setOpcode(InsertOp); else Inst.setOpcode(ExtractOp); return MCDisassembler::Success; }
bool DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst) { return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get()); }
static DecodeStatus DecodeLDSTPairInstruction(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus Result = MCDisassembler::Success; unsigned Rt = fieldFromInstruction(Insn, 0, 5); unsigned Rn = fieldFromInstruction(Insn, 5, 5); unsigned Rt2 = fieldFromInstruction(Insn, 10, 5); unsigned SImm7 = fieldFromInstruction(Insn, 15, 7); unsigned L = fieldFromInstruction(Insn, 22, 1); unsigned V = fieldFromInstruction(Insn, 26, 1); unsigned Opc = fieldFromInstruction(Insn, 30, 2); // Not an official name, but it turns out that bit 23 distinguishes indexed // from non-indexed operations. unsigned Indexed = fieldFromInstruction(Insn, 23, 1); if (Indexed && L == 0) { // The MCInst for an indexed store has an out operand and 4 ins: // Rn_wb, Rt, Rt2, Rn, Imm DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); } // You shouldn't load to the same register twice in an instruction... if (L && Rt == Rt2) Result = MCDisassembler::SoftFail; // ... or do any operation that writes-back to a transfer register. But note // that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different. if (Indexed && V == 0 && Rn != 31 && (Rt == Rn || Rt2 == Rn)) Result = MCDisassembler::SoftFail; // Exactly how we decode the MCInst's registers depends on the Opc and V // fields of the instruction. These also obviously determine the size of the // operation so we can fill in that information while we're at it. if (V) { // The instruction operates on the FP/SIMD registers switch (Opc) { default: return MCDisassembler::Fail; case 0: DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder); DecodeFPR32RegisterClass(Inst, Rt2, Address, Decoder); break; case 1: DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder); DecodeFPR64RegisterClass(Inst, Rt2, Address, Decoder); break; case 2: DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder); DecodeFPR128RegisterClass(Inst, Rt2, Address, Decoder); break; } } else { switch (Opc) { default: return MCDisassembler::Fail; case 0: DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder); DecodeGPR32RegisterClass(Inst, Rt2, Address, Decoder); break; case 1: assert(L && "unexpected \"store signed\" attempt"); DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder); DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder); break; case 2: DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder); DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder); break; } } if (Indexed && L == 1) { // The MCInst for an indexed load has 3 out operands and an 3 ins: // Rt, Rt2, Rn_wb, Rt2, Rn, Imm DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); } DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); Inst.addOperand(MCOperand::CreateImm(SImm7)); return Result; }
// 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); } }