blob: ffc09eb9f16cf0cbff9b1a7e2697db0ec0fa76dc [file] [log] [blame]
Daniel Dunbarfc6877a2009-06-29 20:40:36 +00001//===- AsmExpr.cpp - Assembly file expressions ----------------------------===//
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#include "AsmExpr.h"
11#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
16AsmExpr::~AsmExpr() {
17}
18
19bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
Daniel Dunbar15d17072009-06-30 01:49:52 +000020 MCValue Value;
21
22 if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isConstant())
23 return false;
24
25 Res = Value.getConstant();
26 return true;
27}
28
29bool AsmExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000030 switch (getKind()) {
31 default:
32 assert(0 && "Invalid assembly expression kind!");
33
34 case Constant:
Daniel Dunbar15d17072009-06-30 01:49:52 +000035 Res = MCValue::get(cast<AsmConstantExpr>(this)->getValue());
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000036 return true;
37
38 case SymbolRef: {
39 MCSymbol *Sym = cast<AsmSymbolRefExpr>(this)->getSymbol();
Daniel Dunbar15d17072009-06-30 01:49:52 +000040 if (const MCValue *Value = Ctx.GetSymbolValue(Sym))
41 Res = *Value;
42 else
43 Res = MCValue::get(Sym, 0, 0);
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000044 return true;
45 }
46
47 case Unary: {
48 const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this);
Daniel Dunbar15d17072009-06-30 01:49:52 +000049 MCValue Value;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000050
Daniel Dunbar15d17072009-06-30 01:49:52 +000051 if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000052 return false;
53
54 switch (AUE->getOpcode()) {
Daniel Dunbar15d17072009-06-30 01:49:52 +000055 case AsmUnaryExpr::LNot:
56 if (!Value.isConstant())
57 return false;
58 Res = MCValue::get(!Value.getConstant());
59 break;
60 case AsmUnaryExpr::Minus:
61 /// -(a - b + const) ==> (b - a - const)
62 if (Value.getSymA() && !Value.getSymA())
63 return false;
64 Res = MCValue::get(Value.getSymB(), Value.getSymA(),
65 -Value.getConstant());
66 break;
67 case AsmUnaryExpr::Not:
68 if (!Value.isConstant())
69 return false;
70 Res = MCValue::get(~Value.getConstant());
71 break;
72 case AsmUnaryExpr::Plus:
73 Res = Value;
74 break;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000075 }
76
77 return true;
78 }
79
80 case Binary: {
81 const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this);
Daniel Dunbar15d17072009-06-30 01:49:52 +000082 MCValue LHSValue, RHSValue;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000083
Daniel Dunbar15d17072009-06-30 01:49:52 +000084 if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
85 !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
Daniel Dunbarfc6877a2009-06-29 20:40:36 +000086 return false;
87
Daniel Dunbar15d17072009-06-30 01:49:52 +000088 // We only support a few operations on non-constant expressions, handle
89 // those first.
90 if (!LHSValue.isConstant() || !RHSValue.isConstant()) {
91 switch (ABE->getOpcode()) {
92 default:
93 return false;
94 case AsmBinaryExpr::Sub:
95 // Negate RHS and fall through.
96 RHSValue = MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(),
97 -RHSValue.getConstant());
98 case AsmBinaryExpr::Add:
99 // (a_0 - b_0 + cst_0) + (a_1 - b_1 + cst_1)
100
101 // We can't add or subtract two symbols.
102 if ((LHSValue.getSymA() && RHSValue.getSymB()) ||
103 (LHSValue.getSymB() && RHSValue.getSymB()))
104 return false;
105
106 MCSymbol *A =
107 LHSValue.getSymA() ? LHSValue.getSymA() : RHSValue.getSymA();
108 MCSymbol *B =
109 LHSValue.getSymB() ? LHSValue.getSymB() : RHSValue.getSymB();
110 if (B) {
111 // If we have a negated symbol, then we must have also have a
112 // non-negated symbol, and both symbols must be in the same
113 // non-external section. We can do this check later to permit
114 // expressions which eventually fold to a representable form -- such
115 // as (a + (0 - b)) -- if necessary.
116 if (!A || !A->getSection() || A->getSection() != B->getSection())
117 return false;
118 }
119 Res = MCValue::get(A, B,
120 LHSValue.getConstant() + RHSValue.getConstant());
121 return true;
122 }
123 }
124
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000125 // FIXME: We need target hooks for the evaluation. It may be limited in
126 // width, and gas defines the result of comparisons differently from Apple
127 // as (the result is sign extended).
Daniel Dunbar15d17072009-06-30 01:49:52 +0000128 int64_t Result, LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000129 switch (ABE->getOpcode()) {
Daniel Dunbar15d17072009-06-30 01:49:52 +0000130 case AsmBinaryExpr::Add: Result = LHS + RHS; break;
131 case AsmBinaryExpr::And: Result = LHS & RHS; break;
132 case AsmBinaryExpr::Div: Result = LHS / RHS; break;
133 case AsmBinaryExpr::EQ: Result = LHS == RHS; break;
134 case AsmBinaryExpr::GT: Result = LHS > RHS; break;
135 case AsmBinaryExpr::GTE: Result = LHS >= RHS; break;
136 case AsmBinaryExpr::LAnd: Result = LHS && RHS; break;
137 case AsmBinaryExpr::LOr: Result = LHS || RHS; break;
138 case AsmBinaryExpr::LT: Result = LHS < RHS; break;
139 case AsmBinaryExpr::LTE: Result = LHS <= RHS; break;
140 case AsmBinaryExpr::Mod: Result = LHS % RHS; break;
141 case AsmBinaryExpr::Mul: Result = LHS * RHS; break;
142 case AsmBinaryExpr::NE: Result = LHS != RHS; break;
143 case AsmBinaryExpr::Or: Result = LHS | RHS; break;
144 case AsmBinaryExpr::Shl: Result = LHS << RHS; break;
145 case AsmBinaryExpr::Shr: Result = LHS >> RHS; break;
146 case AsmBinaryExpr::Sub: Result = LHS - RHS; break;
147 case AsmBinaryExpr::Xor: Result = LHS ^ RHS; break;
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000148 }
149
Daniel Dunbar15d17072009-06-30 01:49:52 +0000150 Res = MCValue::get(Result);
Daniel Dunbarfc6877a2009-06-29 20:40:36 +0000151 return true;
152 }
153 }
154}
155