MCExpr.cpp revision 198396
1209513Simp//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// 2209513Simp// 3209552Simp// The LLVM Compiler Infrastructure 4209513Simp// 5209513Simp// This file is distributed under the University of Illinois Open Source 6209513Simp// License. See LICENSE.TXT for details. 7209513Simp// 8209513Simp//===----------------------------------------------------------------------===// 9209513Simp 10209513Simp#include "llvm/MC/MCExpr.h" 11209513Simp#include "llvm/MC/MCContext.h" 12209513Simp#include "llvm/MC/MCSymbol.h" 13209513Simp#include "llvm/MC/MCValue.h" 14209513Simp#include "llvm/Support/raw_ostream.h" 15209513Simpusing namespace llvm; 16209513Simp 17209513Simpvoid MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { 18209513Simp switch (getKind()) { 19209513Simp case MCExpr::Constant: 20209513Simp OS << cast<MCConstantExpr>(*this).getValue(); 21209513Simp return; 22209513Simp 23209513Simp case MCExpr::SymbolRef: { 24209513Simp const MCSymbol &Sym = cast<MCSymbolRefExpr>(*this).getSymbol(); 25209513Simp 26209513Simp // Parenthesize names that start with $ so that they don't look like 27209513Simp // absolute names. 28209513Simp if (Sym.getName()[0] == '$') { 29209513Simp OS << '('; 30209513Simp Sym.print(OS, MAI); 31209513Simp OS << ')'; 32209513Simp } else { 33209513Simp Sym.print(OS, MAI); 34209513Simp } 35209513Simp return; 36220059Sjpaetzel } 37220059Sjpaetzel 38209513Simp case MCExpr::Unary: { 39209513Simp const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); 40209513Simp switch (UE.getOpcode()) { 41209513Simp default: assert(0 && "Invalid opcode!"); 42209513Simp case MCUnaryExpr::LNot: OS << '!'; break; 43220059Sjpaetzel case MCUnaryExpr::Minus: OS << '-'; break; 44209513Simp case MCUnaryExpr::Not: OS << '~'; break; 45209513Simp case MCUnaryExpr::Plus: OS << '+'; break; 46209513Simp } 47209513Simp UE.getSubExpr()->print(OS, MAI); 48209513Simp return; 49209513Simp } 50209513Simp 51209513Simp case MCExpr::Binary: { 52209513Simp const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); 53232899Sjpaetzel 54220059Sjpaetzel // Only print parens around the LHS if it is non-trivial. 55209513Simp if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { 56209513Simp BE.getLHS()->print(OS, MAI); 57220059Sjpaetzel } else { 58220059Sjpaetzel OS << '('; 59209513Simp BE.getLHS()->print(OS, MAI); 60232899Sjpaetzel OS << ')'; 61209513Simp } 62232510Seadler 63220059Sjpaetzel switch (BE.getOpcode()) { 64211488Simp default: assert(0 && "Invalid opcode!"); 65211488Simp case MCBinaryExpr::Add: 66211488Simp // Print "X-42" instead of "X+-42". 67209513Simp if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { 68209513Simp if (RHSC->getValue() < 0) { 69209513Simp OS << RHSC->getValue(); 70209513Simp return; 71209513Simp } 72209513Simp } 73209513Simp 74209513Simp OS << '+'; 75209513Simp break; 76209513Simp case MCBinaryExpr::And: OS << '&'; break; 77209513Simp case MCBinaryExpr::Div: OS << '/'; break; 78225657Sjpaetzel case MCBinaryExpr::EQ: OS << "=="; break; 79225657Sjpaetzel case MCBinaryExpr::GT: OS << '>'; break; 80225657Sjpaetzel case MCBinaryExpr::GTE: OS << ">="; break; 81225657Sjpaetzel case MCBinaryExpr::LAnd: OS << "&&"; break; 82225657Sjpaetzel case MCBinaryExpr::LOr: OS << "||"; break; 83225657Sjpaetzel case MCBinaryExpr::LT: OS << '<'; break; 84225657Sjpaetzel case MCBinaryExpr::LTE: OS << "<="; break; 85225657Sjpaetzel case MCBinaryExpr::Mod: OS << '%'; break; 86225657Sjpaetzel case MCBinaryExpr::Mul: OS << '*'; break; 87209513Simp case MCBinaryExpr::NE: OS << "!="; break; 88209513Simp case MCBinaryExpr::Or: OS << '|'; break; 89209513Simp case MCBinaryExpr::Shl: OS << "<<"; break; 90220059Sjpaetzel case MCBinaryExpr::Shr: OS << ">>"; break; 91209513Simp case MCBinaryExpr::Sub: OS << '-'; break; 92209513Simp case MCBinaryExpr::Xor: OS << '^'; break; 93209513Simp } 94209513Simp 95211730Simp // Only print parens around the LHS if it is non-trivial. 96211730Simp if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { 97211730Simp BE.getRHS()->print(OS, MAI); 98209513Simp } else { 99211730Simp OS << '('; 100211730Simp BE.getRHS()->print(OS, MAI); 101211730Simp OS << ')'; 102211730Simp } 103211730Simp return; 104220059Sjpaetzel } 105220059Sjpaetzel } 106211730Simp 107211730Simp assert(0 && "Invalid expression kind!"); 108211730Simp} 109220059Sjpaetzel 110211730Simpvoid MCExpr::dump() const { 111211730Simp print(errs(), 0); 112211730Simp errs() << '\n'; 113211730Simp} 114211730Simp 115211730Simp/* *** */ 116211730Simp 117211730Simpconst MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS, 118211730Simp const MCExpr *RHS, MCContext &Ctx) { 119209513Simp return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); 120209513Simp} 121209513Simp 122209513Simpconst MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr, 123209513Simp MCContext &Ctx) { 124209513Simp return new (Ctx) MCUnaryExpr(Opc, Expr); 125209513Simp} 126209513Simp 127209513Simpconst MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { 128209513Simp return new (Ctx) MCConstantExpr(Value); 129232899Sjpaetzel} 130232899Sjpaetzel 131232899Sjpaetzelconst MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, 132209513Simp MCContext &Ctx) { 133209513Simp return new (Ctx) MCSymbolRefExpr(Sym); 134209513Simp} 135209513Simp 136209513Simpconst MCSymbolRefExpr *MCSymbolRefExpr::Create(const StringRef &Name, 137209513Simp MCContext &Ctx) { 138209513Simp return Create(Ctx.GetOrCreateSymbol(Name), Ctx); 139209513Simp} 140209513Simp 141209513Simp 142209513Simp/* *** */ 143209513Simp 144209513Simpbool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { 145209513Simp MCValue Value; 146209513Simp 147220059Sjpaetzel if (!EvaluateAsRelocatable(Value) || !Value.isAbsolute()) 148220059Sjpaetzel return false; 149209513Simp 150209513Simp Res = Value.getConstant(); 151209513Simp return true; 152220059Sjpaetzel} 153209513Simp 154209513Simpstatic bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A, 155209513Simp const MCSymbol *RHS_B, int64_t RHS_Cst, 156209513Simp MCValue &Res) { 157209513Simp // We can't add or subtract two symbols. 158209513Simp if ((LHS.getSymA() && RHS_A) || 159209513Simp (LHS.getSymB() && RHS_B)) 160209513Simp return false; 161209513Simp 162209513Simp const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A; 163220059Sjpaetzel const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B; 164209513Simp if (B) { 165209513Simp // If we have a negated symbol, then we must have also have a non-negated 166217229Sjpaetzel // symbol in order to encode the expression. We can do this check later to 167217229Sjpaetzel // permit expressions which eventually fold to a representable form -- such 168209513Simp // as (a + (0 - b)) -- if necessary. 169217229Sjpaetzel if (!A) 170217229Sjpaetzel return false; 171217229Sjpaetzel } 172217229Sjpaetzel Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst); 173217229Sjpaetzel return true; 174209513Simp} 175209513Simp 176217229Sjpaetzelbool MCExpr::EvaluateAsRelocatable(MCValue &Res) const { 177217229Sjpaetzel switch (getKind()) { 178217229Sjpaetzel case Constant: 179217229Sjpaetzel Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 180217229Sjpaetzel return true; 181217229Sjpaetzel 182227368Sjpaetzel case SymbolRef: { 183227368Sjpaetzel const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol(); 184227368Sjpaetzel 185217229Sjpaetzel // Evaluate recursively if this is a variable. 186209513Simp if (Sym.isVariable()) 187209513Simp return Sym.getValue()->EvaluateAsRelocatable(Res); 188209513Simp 189209513Simp Res = MCValue::get(&Sym, 0, 0); 190220059Sjpaetzel return true; 191220059Sjpaetzel } 192209513Simp 193209513Simp case Unary: { 194209513Simp const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 195209513Simp MCValue Value; 196209513Simp 197209513Simp if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value)) 198209513Simp return false; 199209513Simp 200209513Simp switch (AUE->getOpcode()) { 201209513Simp case MCUnaryExpr::LNot: 202209513Simp if (!Value.isAbsolute()) 203209513Simp return false; 204220059Sjpaetzel Res = MCValue::get(!Value.getConstant()); 205220059Sjpaetzel break; 206209513Simp case MCUnaryExpr::Minus: 207209513Simp /// -(a - b + const) ==> (b - a - const) 208209513Simp if (Value.getSymA() && !Value.getSymB()) 209209513Simp return false; 210209513Simp Res = MCValue::get(Value.getSymB(), Value.getSymA(), 211209513Simp -Value.getConstant()); 212209513Simp break; 213209513Simp case MCUnaryExpr::Not: 214209513Simp if (!Value.isAbsolute()) 215209513Simp return false; 216209513Simp Res = MCValue::get(~Value.getConstant()); 217209513Simp break; 218209513Simp case MCUnaryExpr::Plus: 219209513Simp Res = Value; 220220059Sjpaetzel break; 221209513Simp } 222220059Sjpaetzel 223209513Simp return true; 224209513Simp } 225209513Simp 226209513Simp case Binary: { 227213647Simp const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 228209513Simp MCValue LHSValue, RHSValue; 229209513Simp 230209513Simp if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue) || 231209513Simp !ABE->getRHS()->EvaluateAsRelocatable(RHSValue)) 232209513Simp return false; 233220059Sjpaetzel 234209513Simp // We only support a few operations on non-constant expressions, handle 235209513Simp // those first. 236209513Simp if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 237209513Simp switch (ABE->getOpcode()) { 238220059Sjpaetzel default: 239220059Sjpaetzel return false; 240209513Simp case MCBinaryExpr::Sub: 241209513Simp // Negate RHS and add. 242209513Simp return EvaluateSymbolicAdd(LHSValue, 243209513Simp RHSValue.getSymB(), RHSValue.getSymA(), 244209513Simp -RHSValue.getConstant(), 245209513Simp Res); 246209513Simp 247209513Simp case MCBinaryExpr::Add: 248209513Simp return EvaluateSymbolicAdd(LHSValue, 249209513Simp RHSValue.getSymA(), RHSValue.getSymB(), 250209513Simp RHSValue.getConstant(), 251209513Simp Res); 252220059Sjpaetzel } 253220059Sjpaetzel } 254217229Sjpaetzel 255220059Sjpaetzel // FIXME: We need target hooks for the evaluation. It may be limited in 256209513Simp // width, and gas defines the result of comparisons differently from Apple 257217229Sjpaetzel // as (the result is sign extended). 258220059Sjpaetzel int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 259217229Sjpaetzel int64_t Result = 0; 260227368Sjpaetzel switch (ABE->getOpcode()) { 261227368Sjpaetzel case MCBinaryExpr::Add: Result = LHS + RHS; break; 262227368Sjpaetzel case MCBinaryExpr::And: Result = LHS & RHS; break; 263209513Simp case MCBinaryExpr::Div: Result = LHS / RHS; break; 264209513Simp case MCBinaryExpr::EQ: Result = LHS == RHS; break; 265209513Simp case MCBinaryExpr::GT: Result = LHS > RHS; break; 266220059Sjpaetzel case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 267220059Sjpaetzel case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 268217229Sjpaetzel case MCBinaryExpr::LOr: Result = LHS || RHS; break; 269209513Simp case MCBinaryExpr::LT: Result = LHS < RHS; break; 270209513Simp case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 271217229Sjpaetzel case MCBinaryExpr::Mod: Result = LHS % RHS; break; 272217229Sjpaetzel case MCBinaryExpr::Mul: Result = LHS * RHS; break; 273217229Sjpaetzel case MCBinaryExpr::NE: Result = LHS != RHS; break; 274227368Sjpaetzel case MCBinaryExpr::Or: Result = LHS | RHS; break; 275227368Sjpaetzel case MCBinaryExpr::Shl: Result = LHS << RHS; break; 276227368Sjpaetzel case MCBinaryExpr::Shr: Result = LHS >> RHS; break; 277217229Sjpaetzel case MCBinaryExpr::Sub: Result = LHS - RHS; break; 278217229Sjpaetzel case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 279217229Sjpaetzel } 280217229Sjpaetzel 281209513Simp Res = MCValue::get(Result); 282209513Simp return true; 283209513Simp } 284209513Simp } 285209513Simp 286209513Simp assert(0 && "Invalid assembly expression kind!"); 287209513Simp return false; 288217229Sjpaetzel} 289217229Sjpaetzel