1dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//===- AArch64ExternalSymbolizer.cpp - Symbolizer for AArch64 ---*- C++ -*-===// 2dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// 3dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// The LLVM Compiler Infrastructure 4dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// 5dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// This file is distributed under the University of Illinois Open Source 6dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// License. See LICENSE.TXT for details. 7dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// 8dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//===----------------------------------------------------------------------===// 9dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 10dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "AArch64ExternalSymbolizer.h" 11dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "AArch64Subtarget.h" 12dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "MCTargetDesc/AArch64AddressingModes.h" 13dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "Utils/AArch64BaseInfo.h" 14dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/MC/MCContext.h" 15dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/MC/MCExpr.h" 16dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/MC/MCInst.h" 17dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/Support/Format.h" 18dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/Support/raw_ostream.h" 19dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 20dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesusing namespace llvm; 21dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 22dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "aarch64-disassembler" 23dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 24dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic MCSymbolRefExpr::VariantKind 25dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesgetVariant(uint64_t LLVMDisassembler_VariantKind) { 26dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines switch (LLVMDisassembler_VariantKind) { 27dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case LLVMDisassembler_VariantKind_None: 28dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return MCSymbolRefExpr::VK_None; 29dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case LLVMDisassembler_VariantKind_ARM64_PAGE: 30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return MCSymbolRefExpr::VK_PAGE; 31dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case LLVMDisassembler_VariantKind_ARM64_PAGEOFF: 32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return MCSymbolRefExpr::VK_PAGEOFF; 33dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case LLVMDisassembler_VariantKind_ARM64_GOTPAGE: 34dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return MCSymbolRefExpr::VK_GOTPAGE; 35dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF: 36dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return MCSymbolRefExpr::VK_GOTPAGEOFF; 37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case LLVMDisassembler_VariantKind_ARM64_TLVP: 38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case LLVMDisassembler_VariantKind_ARM64_TLVOFF: 39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines default: 40cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines llvm_unreachable("bad LLVMDisassembler_VariantKind"); 41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic 45dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// operand in place of the immediate Value in the MCInst. The immediate 46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Value has not had any PC adjustment made by the caller. If the instruction 47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// is a branch that adds the PC to the immediate Value then isBranch is 48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Success, else Fail. If GetOpInfo is non-null, then it is called to get any 49dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// symbolic information at the Address for this instrution. If that returns 50dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// non-zero then the symbolic information it returns is used to create an 51dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// MCExpr and that is added as an operand to the MCInst. If GetOpInfo() 52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// returns zero and isBranch is Success then a symbol look up for 53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// Address + Value is done and if a symbol is found an MCExpr is created with 54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// that, else an MCExpr with Address + Value is created. If GetOpInfo() 55dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// returns zero and isBranch is Fail then the the Opcode of the MCInst is 56dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// tested and for ADRP an other instructions that help to load of pointers 57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// a symbol look up is done to see it is returns a specific reference type 58dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// to add to the comment stream. This function returns Success if it adds 59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// an operand to the MCInst and Fail otherwise. 60dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool AArch64ExternalSymbolizer::tryAddingSymbolicOperand( 61dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCInst &MI, raw_ostream &CommentStream, int64_t Value, uint64_t Address, 62dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool IsBranch, uint64_t Offset, uint64_t InstSize) { 63dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // FIXME: This method shares a lot of code with 64dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // MCExternalSymbolizer::tryAddingSymbolicOperand. It may be possible 65dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // refactor the MCExternalSymbolizer interface to allow more of this 66dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // implementation to be shared. 67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // 68dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines struct LLVMOpInfo1 SymbolicOp; 69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); 70dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolicOp.Value = Value; 71dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint64_t ReferenceType; 72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const char *ReferenceName; 73dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!GetOpInfo || 74dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines !GetOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) { 75dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (IsBranch) { 76dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; 77dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const char *Name = SymbolLookUp(DisInfo, Address + Value, &ReferenceType, 78dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Address, &ReferenceName); 79dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Name) { 80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolicOp.AddSymbol.Name = Name; 81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolicOp.AddSymbol.Present = true; 82dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolicOp.Value = 0; 83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 84dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolicOp.Value = Address + Value; 85dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 86dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) 87dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "symbol stub for: " << ReferenceName; 88dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (ReferenceType == 89dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVMDisassembler_ReferenceType_Out_Objc_Message) 90dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "Objc message: " << ReferenceName; 91dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else if (MI.getOpcode() == AArch64::ADRP) { 92dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADRP; 93dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // otool expects the fully encoded ADRP instruction to be passed in as 94dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // the value here, so reconstruct it: 95dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCRegisterInfo &MCRI = *Ctx.getRegisterInfo(); 96dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t EncodedInst = 0x90000000; 97dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EncodedInst |= (Value & 0x3) << 29; // immlo 98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EncodedInst |= ((Value >> 2) & 0x7FFFF) << 5; // immhi 99dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EncodedInst |= MCRI.getEncodingValue(MI.getOperand(0).getReg()); // reg 100dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolLookUp(DisInfo, EncodedInst, &ReferenceType, Address, 101dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines &ReferenceName); 102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << format("0x%llx", 103dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 0xfffffffffffff000LL & (Address + Value)); 104dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else if (MI.getOpcode() == AArch64::ADDXri || 105dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MI.getOpcode() == AArch64::LDRXui || 106dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MI.getOpcode() == AArch64::LDRXl || 107dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MI.getOpcode() == AArch64::ADR) { 108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (MI.getOpcode() == AArch64::ADDXri) 109dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADDXri; 110dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (MI.getOpcode() == AArch64::LDRXui) 111dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_LDRXui; 112dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (MI.getOpcode() == AArch64::LDRXl) { 113dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_LDRXl; 114dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolLookUp(DisInfo, Address + Value, &ReferenceType, Address, 115dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines &ReferenceName); 116dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else if (MI.getOpcode() == AArch64::ADR) { 117dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADR; 118dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolLookUp(DisInfo, Address + Value, &ReferenceType, Address, 119dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines &ReferenceName); 120dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 121dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCRegisterInfo &MCRI = *Ctx.getRegisterInfo(); 122dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // otool expects the fully encoded ADD/LDR instruction to be passed in 123dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // as the value here, so reconstruct it: 124dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines unsigned EncodedInst = 125dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MI.getOpcode() == AArch64::ADDXri ? 0x91000000: 0xF9400000; 126dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EncodedInst |= Value << 10; // imm12 [+ shift:2 for ADD] 127dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EncodedInst |= 128dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCRI.getEncodingValue(MI.getOperand(1).getReg()) << 5; // Rn 129dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EncodedInst |= MCRI.getEncodingValue(MI.getOperand(0).getReg()); // Rd 130dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 131dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolLookUp(DisInfo, EncodedInst, &ReferenceType, Address, 132dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines &ReferenceName); 133dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 134dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr) 135dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "literal pool symbol address: " << ReferenceName; 136dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (ReferenceType == 137dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) 138dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "literal pool for: \"" << ReferenceName << "\""; 139dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (ReferenceType == 140dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref) 141dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "Objc cfstring ref: @\"" << ReferenceName << "\""; 142dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (ReferenceType == 143dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVMDisassembler_ReferenceType_Out_Objc_Message) 144dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "Objc message: " << ReferenceName; 145dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (ReferenceType == 146dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref) 147dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "Objc message ref: " << ReferenceName; 148dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (ReferenceType == 149dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref) 150dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "Objc selector ref: " << ReferenceName; 151dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (ReferenceType == 152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref) 153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CommentStream << "Objc class ref: " << ReferenceName; 154dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // For these instructions, the SymbolLookUp() above is just to get the 155dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // ReferenceType and ReferenceName. We want to make sure not to 156dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // fall through so we don't build an MCExpr to leave the disassembly 157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // of the immediate values of these instructions to the InstPrinter. 158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return false; 159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return false; 161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 164dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCExpr *Add = nullptr; 165dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (SymbolicOp.AddSymbol.Present) { 166dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (SymbolicOp.AddSymbol.Name) { 167dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines StringRef Name(SymbolicOp.AddSymbol.Name); 168dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); 169dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCSymbolRefExpr::VariantKind Variant = getVariant(SymbolicOp.VariantKind); 170dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Variant != MCSymbolRefExpr::VK_None) 171dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Add = MCSymbolRefExpr::Create(Sym, Variant, Ctx); 172dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else 173dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Add = MCSymbolRefExpr::Create(Sym, Ctx); 174dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 175dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, Ctx); 176dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 177dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 178dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 179dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCExpr *Sub = nullptr; 180dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (SymbolicOp.SubtractSymbol.Present) { 181dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (SymbolicOp.SubtractSymbol.Name) { 182dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines StringRef Name(SymbolicOp.SubtractSymbol.Name); 183dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); 184dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Sub = MCSymbolRefExpr::Create(Sym, Ctx); 185dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 186dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, Ctx); 187dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 188dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 189dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 190dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCExpr *Off = nullptr; 191dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (SymbolicOp.Value != 0) 192dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Off = MCConstantExpr::Create(SymbolicOp.Value, Ctx); 193dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 194dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCExpr *Expr; 195dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Sub) { 196dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCExpr *LHS; 197dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Add) 198dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LHS = MCBinaryExpr::CreateSub(Add, Sub, Ctx); 199dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else 200dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LHS = MCUnaryExpr::CreateMinus(Sub, Ctx); 201dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Off) 202dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Expr = MCBinaryExpr::CreateAdd(LHS, Off, Ctx); 203dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else 204dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Expr = LHS; 205dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else if (Add) { 206dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Off) 207dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Expr = MCBinaryExpr::CreateAdd(Add, Off, Ctx); 208dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else 209dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Expr = Add; 210dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 211dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Off) 212dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Expr = Off; 213dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else 214dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Expr = MCConstantExpr::Create(0, Ctx); 215dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 216dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 217dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MI.addOperand(MCOperand::CreateExpr(Expr)); 218dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 219dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return true; 220dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 221