Fix part 1 of pr4682. PICADD is a 16-bit instruction even in thumb2 mode.
[llvm/avr.git] / tools / llvm-mc / AsmExpr.cpp
blobc3362e4268c85c9ec38389e1d120538950a7255d
1 //===- 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 //===----------------------------------------------------------------------===//
10 #include "AsmExpr.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCSymbol.h"
13 #include "llvm/MC/MCValue.h"
14 using namespace llvm;
16 AsmExpr::~AsmExpr() {
19 bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
20 MCValue Value;
22 if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute())
23 return false;
25 Res = Value.getConstant();
26 return true;
29 static bool EvaluateSymbolicAdd(const MCValue &LHS, MCSymbol *RHS_A,
30 MCSymbol *RHS_B, int64_t RHS_Cst,
31 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;
37 MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
38 MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
39 if (B) {
40 // 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
43 // as (a + (0 - b)) -- if necessary.
44 if (!A)
45 return false;
47 Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
48 return true;
51 bool AsmExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
52 switch (getKind()) {
53 default:
54 assert(0 && "Invalid assembly expression kind!");
56 case Constant:
57 Res = MCValue::get(cast<AsmConstantExpr>(this)->getValue());
58 return true;
60 case SymbolRef: {
61 MCSymbol *Sym = cast<AsmSymbolRefExpr>(this)->getSymbol();
62 if (const MCValue *Value = Ctx.GetSymbolValue(Sym))
63 Res = *Value;
64 else
65 Res = MCValue::get(Sym, 0, 0);
66 return true;
69 case Unary: {
70 const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this);
71 MCValue Value;
73 if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
74 return false;
76 switch (AUE->getOpcode()) {
77 case AsmUnaryExpr::LNot:
78 if (!Value.isAbsolute())
79 return false;
80 Res = MCValue::get(!Value.getConstant());
81 break;
82 case AsmUnaryExpr::Minus:
83 /// -(a - b + const) ==> (b - a - const)
84 if (Value.getSymA() && !Value.getSymA())
85 return false;
86 Res = MCValue::get(Value.getSymB(), Value.getSymA(),
87 -Value.getConstant());
88 break;
89 case AsmUnaryExpr::Not:
90 if (!Value.isAbsolute())
91 return false;
92 Res = MCValue::get(~Value.getConstant());
93 break;
94 case AsmUnaryExpr::Plus:
95 Res = Value;
96 break;
99 return true;
102 case Binary: {
103 const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this);
104 MCValue LHSValue, RHSValue;
106 if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
107 !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
108 return false;
110 // We only support a few operations on non-constant expressions, handle
111 // those first.
112 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
113 switch (ABE->getOpcode()) {
114 default:
115 return false;
116 case AsmBinaryExpr::Sub:
117 // Negate RHS and add.
118 return EvaluateSymbolicAdd(LHSValue,
119 RHSValue.getSymB(), RHSValue.getSymA(),
120 -RHSValue.getConstant(),
121 Res);
123 case AsmBinaryExpr::Add:
124 return EvaluateSymbolicAdd(LHSValue,
125 RHSValue.getSymA(), RHSValue.getSymB(),
126 RHSValue.getConstant(),
127 Res);
131 // 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).
134 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
135 int64_t Result = 0;
136 switch (ABE->getOpcode()) {
137 case AsmBinaryExpr::Add: Result = LHS + RHS; break;
138 case AsmBinaryExpr::And: Result = LHS & RHS; break;
139 case AsmBinaryExpr::Div: Result = LHS / RHS; break;
140 case AsmBinaryExpr::EQ: Result = LHS == RHS; break;
141 case AsmBinaryExpr::GT: Result = LHS > RHS; break;
142 case AsmBinaryExpr::GTE: Result = LHS >= RHS; break;
143 case AsmBinaryExpr::LAnd: Result = LHS && RHS; break;
144 case AsmBinaryExpr::LOr: Result = LHS || RHS; break;
145 case AsmBinaryExpr::LT: Result = LHS < RHS; break;
146 case AsmBinaryExpr::LTE: Result = LHS <= RHS; break;
147 case AsmBinaryExpr::Mod: Result = LHS % RHS; break;
148 case AsmBinaryExpr::Mul: Result = LHS * RHS; break;
149 case AsmBinaryExpr::NE: Result = LHS != RHS; break;
150 case AsmBinaryExpr::Or: Result = LHS | RHS; break;
151 case AsmBinaryExpr::Shl: Result = LHS << RHS; break;
152 case AsmBinaryExpr::Shr: Result = LHS >> RHS; break;
153 case AsmBinaryExpr::Sub: Result = LHS - RHS; break;
154 case AsmBinaryExpr::Xor: Result = LHS ^ RHS; break;
157 Res = MCValue::get(Result);
158 return true;