1 //===- AsmExpr.cpp - Assembly file expressions ----------------------------===//
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 //===----------------------------------------------------------------------===//
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCSymbol.h"
13 #include "llvm/MC/MCValue.h"
19 bool AsmExpr::EvaluateAsAbsolute(MCContext
&Ctx
, int64_t &Res
) const {
22 if (!EvaluateAsRelocatable(Ctx
, Value
) || !Value
.isAbsolute())
25 Res
= Value
.getConstant();
29 static bool EvaluateSymbolicAdd(const MCValue
&LHS
, MCSymbol
*RHS_A
,
30 MCSymbol
*RHS_B
, int64_t RHS_Cst
,
32 // We can't add or subtract two symbols.
33 if ((LHS
.getSymA() && RHS_A
) ||
34 (LHS
.getSymB() && RHS_B
))
37 MCSymbol
*A
= LHS
.getSymA() ? LHS
.getSymA() : RHS_A
;
38 MCSymbol
*B
= LHS
.getSymB() ? LHS
.getSymB() : RHS_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.
47 Res
= MCValue::get(A
, B
, LHS
.getConstant() + RHS_Cst
);
51 bool AsmExpr::EvaluateAsRelocatable(MCContext
&Ctx
, MCValue
&Res
) const {
54 assert(0 && "Invalid assembly expression kind!");
57 Res
= MCValue::get(cast
<AsmConstantExpr
>(this)->getValue());
61 MCSymbol
*Sym
= cast
<AsmSymbolRefExpr
>(this)->getSymbol();
62 if (const MCValue
*Value
= Ctx
.GetSymbolValue(Sym
))
65 Res
= MCValue::get(Sym
, 0, 0);
70 const AsmUnaryExpr
*AUE
= cast
<AsmUnaryExpr
>(this);
73 if (!AUE
->getSubExpr()->EvaluateAsRelocatable(Ctx
, Value
))
76 switch (AUE
->getOpcode()) {
77 case AsmUnaryExpr::LNot
:
78 if (!Value
.isAbsolute())
80 Res
= MCValue::get(!Value
.getConstant());
82 case AsmUnaryExpr::Minus
:
83 /// -(a - b + const) ==> (b - a - const)
84 if (Value
.getSymA() && !Value
.getSymA())
86 Res
= MCValue::get(Value
.getSymB(), Value
.getSymA(),
87 -Value
.getConstant());
89 case AsmUnaryExpr::Not
:
90 if (!Value
.isAbsolute())
92 Res
= MCValue::get(~Value
.getConstant());
94 case AsmUnaryExpr::Plus
:
103 const AsmBinaryExpr
*ABE
= cast
<AsmBinaryExpr
>(this);
104 MCValue LHSValue
, RHSValue
;
106 if (!ABE
->getLHS()->EvaluateAsRelocatable(Ctx
, LHSValue
) ||
107 !ABE
->getRHS()->EvaluateAsRelocatable(Ctx
, RHSValue
))
110 // We only support a few operations on non-constant expressions, handle
112 if (!LHSValue
.isAbsolute() || !RHSValue
.isAbsolute()) {
113 switch (ABE
->getOpcode()) {
116 case AsmBinaryExpr::Sub
:
117 // Negate RHS and add.
118 return EvaluateSymbolicAdd(LHSValue
,
119 RHSValue
.getSymB(), RHSValue
.getSymA(),
120 -RHSValue
.getConstant(),
123 case AsmBinaryExpr::Add
:
124 return EvaluateSymbolicAdd(LHSValue
,
125 RHSValue
.getSymA(), RHSValue
.getSymB(),
126 RHSValue
.getConstant(),
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();
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
);