MCExpr.cpp revision 207e06ea0446c51cb1d89f6400ec7becc46487f8
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 157const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name, 158 VariantKind Kind, 159 MCContext &Ctx) { 160 return Create(Ctx.GetOrCreateTemporarySymbol(Name), Kind, Ctx); 161} 162 163StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 164 switch (Kind) { 165 default: 166 case VK_Invalid: return "<<invalid>>"; 167 case VK_None: return "<<none>>"; 168 169 case VK_GOT: return "GOT"; 170 case VK_GOTOFF: return "GOTOFF"; 171 case VK_GOTPCREL: return "GOTPCREL"; 172 case VK_GOTTPOFF: return "GOTTPOFF"; 173 case VK_INDNTPOFF: return "INDNTPOFF"; 174 case VK_NTPOFF: return "NTPOFF"; 175 case VK_PLT: return "PLT"; 176 case VK_TLSGD: return "TLSGD"; 177 case VK_TPOFF: return "TPOFF"; 178 } 179} 180 181MCSymbolRefExpr::VariantKind 182MCSymbolRefExpr::getVariantKindForName(StringRef Name) { 183 return StringSwitch<VariantKind>(Name) 184 .Case("GOT", VK_GOT) 185 .Case("GOTOFF", VK_GOTOFF) 186 .Case("GOTPCREL", VK_GOTPCREL) 187 .Case("GOTTPOFF", VK_GOTTPOFF) 188 .Case("INDNTPOFF", VK_INDNTPOFF) 189 .Case("NTPOFF", VK_NTPOFF) 190 .Case("PLT", VK_PLT) 191 .Case("TLSGD", VK_TLSGD) 192 .Case("TPOFF", VK_TPOFF) 193 .Default(VK_Invalid); 194} 195 196/* *** */ 197 198void MCTargetExpr::Anchor() {} 199 200/* *** */ 201 202bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const { 203 MCValue Value; 204 205 // Fast path constants. 206 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 207 Res = CE->getValue(); 208 return true; 209 } 210 211 if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute()) 212 return false; 213 214 Res = Value.getConstant(); 215 return true; 216} 217 218static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A, 219 const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst, 220 MCValue &Res) { 221 // We can't add or subtract two symbols. 222 if ((LHS.getSymA() && RHS_A) || 223 (LHS.getSymB() && RHS_B)) 224 return false; 225 226 const MCSymbolRefExpr *A = LHS.getSymA() ? LHS.getSymA() : RHS_A; 227 const MCSymbolRefExpr *B = LHS.getSymB() ? LHS.getSymB() : RHS_B; 228 if (B) { 229 // If we have a negated symbol, then we must have also have a non-negated 230 // symbol in order to encode the expression. We can do this check later to 231 // permit expressions which eventually fold to a representable form -- such 232 // as (a + (0 - b)) -- if necessary. 233 if (!A) 234 return false; 235 } 236 Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst); 237 return true; 238} 239 240bool MCExpr::EvaluateAsRelocatable(MCValue &Res, 241 const MCAsmLayout *Layout) const { 242 ++stats::MCExprEvaluate; 243 244 switch (getKind()) { 245 case Target: 246 return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout); 247 248 case Constant: 249 Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 250 return true; 251 252 case SymbolRef: { 253 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 254 const MCSymbol &Sym = SRE->getSymbol(); 255 256 // Evaluate recursively if this is a variable. 257 if (Sym.isVariable()) { 258 if (!Sym.getValue()->EvaluateAsRelocatable(Res, Layout)) 259 return false; 260 261 // Absolutize symbol differences between defined symbols when we have a 262 // layout object and the target requests it. 263 if (Layout && Res.getSymB() && 264 Layout->getAssembler().getBackend().hasAbsolutizedSet() && 265 Res.getSymA()->getSymbol().isDefined() && 266 Res.getSymB()->getSymbol().isDefined()) { 267 MCSymbolData &A = 268 Layout->getAssembler().getSymbolData(Res.getSymA()->getSymbol()); 269 MCSymbolData &B = 270 Layout->getAssembler().getSymbolData(Res.getSymB()->getSymbol()); 271 Res = MCValue::get(+ Layout->getSymbolAddress(&A) + A.getOffset() 272 - Layout->getSymbolAddress(&B) - B.getOffset() 273 + Res.getConstant()); 274 } 275 276 return true; 277 } 278 279 Res = MCValue::get(SRE, 0, 0); 280 return true; 281 } 282 283 case Unary: { 284 const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 285 MCValue Value; 286 287 if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout)) 288 return false; 289 290 switch (AUE->getOpcode()) { 291 case MCUnaryExpr::LNot: 292 if (!Value.isAbsolute()) 293 return false; 294 Res = MCValue::get(!Value.getConstant()); 295 break; 296 case MCUnaryExpr::Minus: 297 /// -(a - b + const) ==> (b - a - const) 298 if (Value.getSymA() && !Value.getSymB()) 299 return false; 300 Res = MCValue::get(Value.getSymB(), Value.getSymA(), 301 -Value.getConstant()); 302 break; 303 case MCUnaryExpr::Not: 304 if (!Value.isAbsolute()) 305 return false; 306 Res = MCValue::get(~Value.getConstant()); 307 break; 308 case MCUnaryExpr::Plus: 309 Res = Value; 310 break; 311 } 312 313 return true; 314 } 315 316 case Binary: { 317 const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 318 MCValue LHSValue, RHSValue; 319 320 if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) || 321 !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout)) 322 return false; 323 324 // We only support a few operations on non-constant expressions, handle 325 // those first. 326 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 327 switch (ABE->getOpcode()) { 328 default: 329 return false; 330 case MCBinaryExpr::Sub: 331 // Negate RHS and add. 332 return EvaluateSymbolicAdd(LHSValue, 333 RHSValue.getSymB(), RHSValue.getSymA(), 334 -RHSValue.getConstant(), 335 Res); 336 337 case MCBinaryExpr::Add: 338 return EvaluateSymbolicAdd(LHSValue, 339 RHSValue.getSymA(), RHSValue.getSymB(), 340 RHSValue.getConstant(), 341 Res); 342 } 343 } 344 345 // FIXME: We need target hooks for the evaluation. It may be limited in 346 // width, and gas defines the result of comparisons and right shifts 347 // differently from Apple as. 348 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 349 int64_t Result = 0; 350 switch (ABE->getOpcode()) { 351 case MCBinaryExpr::Add: Result = LHS + RHS; break; 352 case MCBinaryExpr::And: Result = LHS & RHS; break; 353 case MCBinaryExpr::Div: Result = LHS / RHS; break; 354 case MCBinaryExpr::EQ: Result = LHS == RHS; break; 355 case MCBinaryExpr::GT: Result = LHS > RHS; break; 356 case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 357 case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 358 case MCBinaryExpr::LOr: Result = LHS || RHS; break; 359 case MCBinaryExpr::LT: Result = LHS < RHS; break; 360 case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 361 case MCBinaryExpr::Mod: Result = LHS % RHS; break; 362 case MCBinaryExpr::Mul: Result = LHS * RHS; break; 363 case MCBinaryExpr::NE: Result = LHS != RHS; break; 364 case MCBinaryExpr::Or: Result = LHS | RHS; break; 365 case MCBinaryExpr::Shl: Result = LHS << RHS; break; 366 case MCBinaryExpr::Shr: Result = LHS >> RHS; break; 367 case MCBinaryExpr::Sub: Result = LHS - RHS; break; 368 case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 369 } 370 371 Res = MCValue::get(Result); 372 return true; 373 } 374 } 375 376 assert(0 && "Invalid assembly expression kind!"); 377 return false; 378} 379