MCExpr.cpp revision 08a408a4b3224627db07eb27e174085d8e1d2426
1//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#define DEBUG_TYPE "mcexpr" 11#include "llvm/MC/MCExpr.h" 12#include "llvm/ADT/Statistic.h" 13#include "llvm/ADT/StringSwitch.h" 14#include "llvm/MC/MCAsmLayout.h" 15#include "llvm/MC/MCAssembler.h" 16#include "llvm/MC/MCContext.h" 17#include "llvm/MC/MCSymbol.h" 18#include "llvm/MC/MCValue.h" 19#include "llvm/Support/Debug.h" 20#include "llvm/Support/raw_ostream.h" 21#include "llvm/Target/TargetAsmBackend.h" 22using namespace llvm; 23 24namespace { 25namespace stats { 26STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); 27} 28} 29 30void MCExpr::print(raw_ostream &OS) const { 31 switch (getKind()) { 32 case MCExpr::Target: 33 return cast<MCTargetExpr>(this)->PrintImpl(OS); 34 case MCExpr::Constant: 35 OS << cast<MCConstantExpr>(*this).getValue(); 36 return; 37 38 case MCExpr::SymbolRef: { 39 const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); 40 const MCSymbol &Sym = SRE.getSymbol(); 41 42 // Parenthesize names that start with $ so that they don't look like 43 // absolute names. 44 if (Sym.getName()[0] == '$') 45 OS << '(' << Sym << ')'; 46 else 47 OS << Sym; 48 49 if (SRE.getKind() != MCSymbolRefExpr::VK_None) 50 OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); 51 52 return; 53 } 54 55 case MCExpr::Unary: { 56 const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); 57 switch (UE.getOpcode()) { 58 default: assert(0 && "Invalid opcode!"); 59 case MCUnaryExpr::LNot: OS << '!'; break; 60 case MCUnaryExpr::Minus: OS << '-'; break; 61 case MCUnaryExpr::Not: OS << '~'; break; 62 case MCUnaryExpr::Plus: OS << '+'; break; 63 } 64 OS << *UE.getSubExpr(); 65 return; 66 } 67 68 case MCExpr::Binary: { 69 const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); 70 71 // Only print parens around the LHS if it is non-trivial. 72 if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { 73 OS << *BE.getLHS(); 74 } else { 75 OS << '(' << *BE.getLHS() << ')'; 76 } 77 78 switch (BE.getOpcode()) { 79 default: assert(0 && "Invalid opcode!"); 80 case MCBinaryExpr::Add: 81 // Print "X-42" instead of "X+-42". 82 if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { 83 if (RHSC->getValue() < 0) { 84 OS << RHSC->getValue(); 85 return; 86 } 87 } 88 89 OS << '+'; 90 break; 91 case MCBinaryExpr::And: OS << '&'; break; 92 case MCBinaryExpr::Div: OS << '/'; break; 93 case MCBinaryExpr::EQ: OS << "=="; break; 94 case MCBinaryExpr::GT: OS << '>'; break; 95 case MCBinaryExpr::GTE: OS << ">="; break; 96 case MCBinaryExpr::LAnd: OS << "&&"; break; 97 case MCBinaryExpr::LOr: OS << "||"; break; 98 case MCBinaryExpr::LT: OS << '<'; break; 99 case MCBinaryExpr::LTE: OS << "<="; break; 100 case MCBinaryExpr::Mod: OS << '%'; break; 101 case MCBinaryExpr::Mul: OS << '*'; break; 102 case MCBinaryExpr::NE: OS << "!="; break; 103 case MCBinaryExpr::Or: OS << '|'; break; 104 case MCBinaryExpr::Shl: OS << "<<"; break; 105 case MCBinaryExpr::Shr: OS << ">>"; break; 106 case MCBinaryExpr::Sub: OS << '-'; break; 107 case MCBinaryExpr::Xor: OS << '^'; break; 108 } 109 110 // Only print parens around the LHS if it is non-trivial. 111 if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { 112 OS << *BE.getRHS(); 113 } else { 114 OS << '(' << *BE.getRHS() << ')'; 115 } 116 return; 117 } 118 } 119 120 assert(0 && "Invalid expression kind!"); 121} 122 123void MCExpr::dump() const { 124 print(dbgs()); 125 dbgs() << '\n'; 126} 127 128/* *** */ 129 130const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS, 131 const MCExpr *RHS, MCContext &Ctx) { 132 return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); 133} 134 135const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr, 136 MCContext &Ctx) { 137 return new (Ctx) MCUnaryExpr(Opc, Expr); 138} 139 140const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { 141 return new (Ctx) MCConstantExpr(Value); 142} 143 144/* *** */ 145 146const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, 147 VariantKind Kind, 148 MCContext &Ctx) { 149 return new (Ctx) MCSymbolRefExpr(Sym, Kind); 150} 151 152const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, 153 MCContext &Ctx) { 154 return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx); 155} 156 157StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 158 switch (Kind) { 159 default: 160 case VK_Invalid: return "<<invalid>>"; 161 case VK_None: return "<<none>>"; 162 163 case VK_GOT: return "GOT"; 164 case VK_GOTOFF: return "GOTOFF"; 165 case VK_GOTPCREL: return "GOTPCREL"; 166 case VK_GOTTPOFF: return "GOTTPOFF"; 167 case VK_INDNTPOFF: return "INDNTPOFF"; 168 case VK_NTPOFF: return "NTPOFF"; 169 case VK_PLT: return "PLT"; 170 case VK_TLSGD: return "TLSGD"; 171 case VK_TPOFF: return "TPOFF"; 172 } 173} 174 175MCSymbolRefExpr::VariantKind 176MCSymbolRefExpr::getVariantKindForName(StringRef Name) { 177 return StringSwitch<VariantKind>(Name) 178 .Case("GOT", VK_GOT) 179 .Case("GOTOFF", VK_GOTOFF) 180 .Case("GOTPCREL", VK_GOTPCREL) 181 .Case("GOTTPOFF", VK_GOTTPOFF) 182 .Case("INDNTPOFF", VK_INDNTPOFF) 183 .Case("NTPOFF", VK_NTPOFF) 184 .Case("PLT", VK_PLT) 185 .Case("TLSGD", VK_TLSGD) 186 .Case("TPOFF", VK_TPOFF) 187 .Default(VK_Invalid); 188} 189 190/* *** */ 191 192void MCTargetExpr::Anchor() {} 193 194/* *** */ 195 196bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const { 197 MCValue Value; 198 199 // Fast path constants. 200 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 201 Res = CE->getValue(); 202 return true; 203 } 204 205 if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute()) 206 return false; 207 208 Res = Value.getConstant(); 209 return true; 210} 211 212static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A, 213 const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst, 214 MCValue &Res) { 215 // We can't add or subtract two symbols. 216 if ((LHS.getSymA() && RHS_A) || 217 (LHS.getSymB() && RHS_B)) 218 return false; 219 220 const MCSymbolRefExpr *A = LHS.getSymA() ? LHS.getSymA() : RHS_A; 221 const MCSymbolRefExpr *B = LHS.getSymB() ? LHS.getSymB() : RHS_B; 222 if (B) { 223 // If we have a negated symbol, then we must have also have a non-negated 224 // symbol in order to encode the expression. We can do this check later to 225 // permit expressions which eventually fold to a representable form -- such 226 // as (a + (0 - b)) -- if necessary. 227 if (!A) 228 return false; 229 } 230 Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst); 231 return true; 232} 233 234bool MCExpr::EvaluateAsRelocatable(MCValue &Res, 235 const MCAsmLayout *Layout) const { 236 ++stats::MCExprEvaluate; 237 238 switch (getKind()) { 239 case Target: 240 return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout); 241 242 case Constant: 243 Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 244 return true; 245 246 case SymbolRef: { 247 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 248 const MCSymbol &Sym = SRE->getSymbol(); 249 250 // Evaluate recursively if this is a variable. 251 if (Sym.isVariable()) { 252 if (!Sym.getVariableValue()->EvaluateAsRelocatable(Res, Layout)) 253 return false; 254 255 // Absolutize symbol differences between defined symbols when we have a 256 // layout object and the target requests it. 257 if (Layout && Res.getSymB() && 258 Layout->getAssembler().getBackend().hasAbsolutizedSet() && 259 Res.getSymA()->getSymbol().isDefined() && 260 Res.getSymB()->getSymbol().isDefined()) { 261 MCSymbolData &A = 262 Layout->getAssembler().getSymbolData(Res.getSymA()->getSymbol()); 263 MCSymbolData &B = 264 Layout->getAssembler().getSymbolData(Res.getSymB()->getSymbol()); 265 Res = MCValue::get(+ Layout->getSymbolAddress(&A) 266 - Layout->getSymbolAddress(&B) 267 + Res.getConstant()); 268 } 269 270 return true; 271 } 272 273 Res = MCValue::get(SRE, 0, 0); 274 return true; 275 } 276 277 case Unary: { 278 const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 279 MCValue Value; 280 281 if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout)) 282 return false; 283 284 switch (AUE->getOpcode()) { 285 case MCUnaryExpr::LNot: 286 if (!Value.isAbsolute()) 287 return false; 288 Res = MCValue::get(!Value.getConstant()); 289 break; 290 case MCUnaryExpr::Minus: 291 /// -(a - b + const) ==> (b - a - const) 292 if (Value.getSymA() && !Value.getSymB()) 293 return false; 294 Res = MCValue::get(Value.getSymB(), Value.getSymA(), 295 -Value.getConstant()); 296 break; 297 case MCUnaryExpr::Not: 298 if (!Value.isAbsolute()) 299 return false; 300 Res = MCValue::get(~Value.getConstant()); 301 break; 302 case MCUnaryExpr::Plus: 303 Res = Value; 304 break; 305 } 306 307 return true; 308 } 309 310 case Binary: { 311 const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 312 MCValue LHSValue, RHSValue; 313 314 if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) || 315 !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout)) 316 return false; 317 318 // We only support a few operations on non-constant expressions, handle 319 // those first. 320 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 321 switch (ABE->getOpcode()) { 322 default: 323 return false; 324 case MCBinaryExpr::Sub: 325 // Negate RHS and add. 326 return EvaluateSymbolicAdd(LHSValue, 327 RHSValue.getSymB(), RHSValue.getSymA(), 328 -RHSValue.getConstant(), 329 Res); 330 331 case MCBinaryExpr::Add: 332 return EvaluateSymbolicAdd(LHSValue, 333 RHSValue.getSymA(), RHSValue.getSymB(), 334 RHSValue.getConstant(), 335 Res); 336 } 337 } 338 339 // FIXME: We need target hooks for the evaluation. It may be limited in 340 // width, and gas defines the result of comparisons and right shifts 341 // differently from Apple as. 342 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 343 int64_t Result = 0; 344 switch (ABE->getOpcode()) { 345 case MCBinaryExpr::Add: Result = LHS + RHS; break; 346 case MCBinaryExpr::And: Result = LHS & RHS; break; 347 case MCBinaryExpr::Div: Result = LHS / RHS; break; 348 case MCBinaryExpr::EQ: Result = LHS == RHS; break; 349 case MCBinaryExpr::GT: Result = LHS > RHS; break; 350 case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 351 case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 352 case MCBinaryExpr::LOr: Result = LHS || RHS; break; 353 case MCBinaryExpr::LT: Result = LHS < RHS; break; 354 case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 355 case MCBinaryExpr::Mod: Result = LHS % RHS; break; 356 case MCBinaryExpr::Mul: Result = LHS * RHS; break; 357 case MCBinaryExpr::NE: Result = LHS != RHS; break; 358 case MCBinaryExpr::Or: Result = LHS | RHS; break; 359 case MCBinaryExpr::Shl: Result = LHS << RHS; break; 360 case MCBinaryExpr::Shr: Result = LHS >> RHS; break; 361 case MCBinaryExpr::Sub: Result = LHS - RHS; break; 362 case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 363 } 364 365 Res = MCValue::get(Result); 366 return true; 367 } 368 } 369 370 assert(0 && "Invalid assembly expression kind!"); 371 return false; 372} 373