1 //===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/MC/MCExpr.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCSymbol.h"
13 #include "llvm/MC/MCValue.h"
16 const MCBinaryExpr * MCBinaryExpr::Create(Opcode Opc,
20 return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
23 const MCUnaryExpr * MCUnaryExpr::Create(Opcode Opc,
26 return new (Ctx) MCUnaryExpr(Opc, Expr);
29 const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
30 return new (Ctx) MCConstantExpr(Value);
33 const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
35 return new (Ctx) MCSymbolRefExpr(Sym);
40 bool MCExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
43 if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute())
46 Res = Value.getConstant();
50 static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A,
51 const MCSymbol *RHS_B, int64_t RHS_Cst,
53 // We can't add or subtract two symbols.
54 if ((LHS.getSymA() && RHS_A) ||
55 (LHS.getSymB() && RHS_B))
58 const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
59 const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
61 // If we have a negated symbol, then we must have also have a non-negated
62 // symbol in order to encode the expression. We can do this check later to
63 // permit expressions which eventually fold to a representable form -- such
64 // as (a + (0 - b)) -- if necessary.
68 Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
72 bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
75 Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
79 const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
80 if (const MCValue *Value = Ctx.GetSymbolValue(&Sym))
83 Res = MCValue::get(&Sym, 0, 0);
88 const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
91 if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
94 switch (AUE->getOpcode()) {
95 case MCUnaryExpr::LNot:
96 if (!Value.isAbsolute())
98 Res = MCValue::get(!Value.getConstant());
100 case MCUnaryExpr::Minus:
101 /// -(a - b + const) ==> (b - a - const)
102 if (Value.getSymA() && !Value.getSymB())
104 Res = MCValue::get(Value.getSymB(), Value.getSymA(),
105 -Value.getConstant());
107 case MCUnaryExpr::Not:
108 if (!Value.isAbsolute())
110 Res = MCValue::get(~Value.getConstant());
112 case MCUnaryExpr::Plus:
121 const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
122 MCValue LHSValue, RHSValue;
124 if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
125 !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
128 // We only support a few operations on non-constant expressions, handle
130 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
131 switch (ABE->getOpcode()) {
134 case MCBinaryExpr::Sub:
135 // Negate RHS and add.
136 return EvaluateSymbolicAdd(LHSValue,
137 RHSValue.getSymB(), RHSValue.getSymA(),
138 -RHSValue.getConstant(),
141 case MCBinaryExpr::Add:
142 return EvaluateSymbolicAdd(LHSValue,
143 RHSValue.getSymA(), RHSValue.getSymB(),
144 RHSValue.getConstant(),
149 // FIXME: We need target hooks for the evaluation. It may be limited in
150 // width, and gas defines the result of comparisons differently from Apple
151 // as (the result is sign extended).
152 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
154 switch (ABE->getOpcode()) {
155 case MCBinaryExpr::Add: Result = LHS + RHS; break;
156 case MCBinaryExpr::And: Result = LHS & RHS; break;
157 case MCBinaryExpr::Div: Result = LHS / RHS; break;
158 case MCBinaryExpr::EQ: Result = LHS == RHS; break;
159 case MCBinaryExpr::GT: Result = LHS > RHS; break;
160 case MCBinaryExpr::GTE: Result = LHS >= RHS; break;
161 case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
162 case MCBinaryExpr::LOr: Result = LHS || RHS; break;
163 case MCBinaryExpr::LT: Result = LHS < RHS; break;
164 case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
165 case MCBinaryExpr::Mod: Result = LHS % RHS; break;
166 case MCBinaryExpr::Mul: Result = LHS * RHS; break;
167 case MCBinaryExpr::NE: Result = LHS != RHS; break;
168 case MCBinaryExpr::Or: Result = LHS | RHS; break;
169 case MCBinaryExpr::Shl: Result = LHS << RHS; break;
170 case MCBinaryExpr::Shr: Result = LHS >> RHS; break;
171 case MCBinaryExpr::Sub: Result = LHS - RHS; break;
172 case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
175 Res = MCValue::get(Result);
180 assert(0 && "Invalid assembly expression kind!");