blob: 91ef7e77ec86e2a9621aa060dae7144d0b74912b [file] [log] [blame]
Daniel Dunbar28c251b2009-08-31 08:06:59 +00001//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
Daniel Dunbarfc6877a2009-06-29 20:40:36 +00002//
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
Daniel Dunbar28c251b2009-08-31 08:06:59 +000010#include "llvm/MC/MCExpr.h"
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000011#include "llvm/MC/MCContext.h"
Daniel Dunbar15d17072009-06-30 01:49:52 +000012#include "llvm/MC/MCSymbol.h"
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000013#include "llvm/MC/MCValue.h"
14using namespace llvm;
15
Daniel Dunbar28c251b2009-08-31 08:06:59 +000016MCExpr::~MCExpr() {
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000017}
18
Daniel Dunbar28c251b2009-08-31 08:06:59 +000019bool MCExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
Daniel Dunbar15d17072009-06-30 01:49:52 +000020 MCValue Value;
21
Daniel Dunbar80f62d02009-07-01 06:48:00 +000022 if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute())
Daniel Dunbar15d17072009-06-30 01:49:52 +000023 return false;
24
25 Res = Value.getConstant();
26 return true;
27}
28
Daniel Dunbard644c322009-08-26 09:16:46 +000029static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A,
30 const MCSymbol *RHS_B, int64_t RHS_Cst,
Daniel Dunbar35976042009-06-30 02:08:27 +000031 MCValue &Res) {
32 // We can't add or subtract two symbols.
33 if ((LHS.getSymA() && RHS_A) ||
34 (LHS.getSymB() && RHS_B))
35 return false;
36
Daniel Dunbard644c322009-08-26 09:16:46 +000037 const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
38 const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
Daniel Dunbar35976042009-06-30 02:08:27 +000039 if (B) {
Daniel Dunbar374d8bd2009-06-30 22:49:27 +000040 // If we have a negated symbol, then we must have also have a non-negated
41 // symbol in order to encode the expression. We can do this check later to
42 // permit expressions which eventually fold to a representable form -- such
Daniel Dunbar35976042009-06-30 02:08:27 +000043 // as (a + (0 - b)) -- if necessary.
Daniel Dunbar374d8bd2009-06-30 22:49:27 +000044 if (!A)
Daniel Dunbar35976042009-06-30 02:08:27 +000045 return false;
46 }
47 Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
48 return true;
49}
50
Daniel Dunbar28c251b2009-08-31 08:06:59 +000051bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000052 switch (getKind()) {
53 default:
54 assert(0 && "Invalid assembly expression kind!");
55
56 case Constant:
Daniel Dunbar28c251b2009-08-31 08:06:59 +000057 Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000058 return true;
59
60 case SymbolRef: {
Daniel Dunbar28c251b2009-08-31 08:06:59 +000061 MCSymbol *Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
Daniel Dunbar15d17072009-06-30 01:49:52 +000062 if (const MCValue *Value = Ctx.GetSymbolValue(Sym))
63 Res = *Value;
64 else
65 Res = MCValue::get(Sym, 0, 0);
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000066 return true;
67 }
68
69 case Unary: {
Daniel Dunbar28c251b2009-08-31 08:06:59 +000070 const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
Daniel Dunbar15d17072009-06-30 01:49:52 +000071 MCValue Value;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000072
Daniel Dunbar15d17072009-06-30 01:49:52 +000073 if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000074 return false;
75
76 switch (AUE->getOpcode()) {
Daniel Dunbar28c251b2009-08-31 08:06:59 +000077 case MCUnaryExpr::LNot:
Daniel Dunbar80f62d02009-07-01 06:48:00 +000078 if (!Value.isAbsolute())
Daniel Dunbar15d17072009-06-30 01:49:52 +000079 return false;
80 Res = MCValue::get(!Value.getConstant());
81 break;
Daniel Dunbar28c251b2009-08-31 08:06:59 +000082 case MCUnaryExpr::Minus:
Daniel Dunbar15d17072009-06-30 01:49:52 +000083 /// -(a - b + const) ==> (b - a - const)
Daniel Dunbarb27a41b2009-08-11 17:47:52 +000084 if (Value.getSymA() && !Value.getSymB())
Daniel Dunbar15d17072009-06-30 01:49:52 +000085 return false;
86 Res = MCValue::get(Value.getSymB(), Value.getSymA(),
87 -Value.getConstant());
88 break;
Daniel Dunbar28c251b2009-08-31 08:06:59 +000089 case MCUnaryExpr::Not:
Daniel Dunbar80f62d02009-07-01 06:48:00 +000090 if (!Value.isAbsolute())
Daniel Dunbar15d17072009-06-30 01:49:52 +000091 return false;
92 Res = MCValue::get(~Value.getConstant());
93 break;
Daniel Dunbar28c251b2009-08-31 08:06:59 +000094 case MCUnaryExpr::Plus:
Daniel Dunbar15d17072009-06-30 01:49:52 +000095 Res = Value;
96 break;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000097 }
98
99 return true;
100 }
101
102 case Binary: {
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000103 const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
Daniel Dunbar15d17072009-06-30 01:49:52 +0000104 MCValue LHSValue, RHSValue;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000105
Daniel Dunbar15d17072009-06-30 01:49:52 +0000106 if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
107 !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000108 return false;
109
Daniel Dunbar15d17072009-06-30 01:49:52 +0000110 // We only support a few operations on non-constant expressions, handle
111 // those first.
Daniel Dunbar80f62d02009-07-01 06:48:00 +0000112 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
Daniel Dunbar15d17072009-06-30 01:49:52 +0000113 switch (ABE->getOpcode()) {
114 default:
115 return false;
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000116 case MCBinaryExpr::Sub:
Daniel Dunbar35976042009-06-30 02:08:27 +0000117 // Negate RHS and add.
118 return EvaluateSymbolicAdd(LHSValue,
119 RHSValue.getSymB(), RHSValue.getSymA(),
120 -RHSValue.getConstant(),
121 Res);
122
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000123 case MCBinaryExpr::Add:
Daniel Dunbar35976042009-06-30 02:08:27 +0000124 return EvaluateSymbolicAdd(LHSValue,
125 RHSValue.getSymA(), RHSValue.getSymB(),
126 RHSValue.getConstant(),
127 Res);
Daniel Dunbar15d17072009-06-30 01:49:52 +0000128 }
129 }
130
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000131 // FIXME: We need target hooks for the evaluation. It may be limited in
132 // width, and gas defines the result of comparisons differently from Apple
133 // as (the result is sign extended).
Daniel Dunbarb79742c2009-06-30 16:02:47 +0000134 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
135 int64_t Result = 0;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000136 switch (ABE->getOpcode()) {
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000137 case MCBinaryExpr::Add: Result = LHS + RHS; break;
138 case MCBinaryExpr::And: Result = LHS & RHS; break;
139 case MCBinaryExpr::Div: Result = LHS / RHS; break;
140 case MCBinaryExpr::EQ: Result = LHS == RHS; break;
141 case MCBinaryExpr::GT: Result = LHS > RHS; break;
142 case MCBinaryExpr::GTE: Result = LHS >= RHS; break;
143 case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
144 case MCBinaryExpr::LOr: Result = LHS || RHS; break;
145 case MCBinaryExpr::LT: Result = LHS < RHS; break;
146 case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
147 case MCBinaryExpr::Mod: Result = LHS % RHS; break;
148 case MCBinaryExpr::Mul: Result = LHS * RHS; break;
149 case MCBinaryExpr::NE: Result = LHS != RHS; break;
150 case MCBinaryExpr::Or: Result = LHS | RHS; break;
151 case MCBinaryExpr::Shl: Result = LHS << RHS; break;
152 case MCBinaryExpr::Shr: Result = LHS >> RHS; break;
153 case MCBinaryExpr::Sub: Result = LHS - RHS; break;
154 case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000155 }
156
Daniel Dunbar15d17072009-06-30 01:49:52 +0000157 Res = MCValue::get(Result);
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000158 return true;
159 }
160 }
161}
162