mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
llvm-mc: Evaluation for relocatable expressions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74496 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -13,6 +13,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class MCSection;
|
||||||
|
|
||||||
class MCSymbol {
|
class MCSymbol {
|
||||||
MCSection *Section;
|
MCSection *Section;
|
||||||
std::string Name;
|
std::string Name;
|
||||||
|
@@ -15,6 +15,8 @@
|
|||||||
#define LLVM_MC_MCVALUE_H
|
#define LLVM_MC_MCVALUE_H
|
||||||
|
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
#include "llvm/MC/MCSymbol.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class MCSymbol;
|
class MCSymbol;
|
||||||
@@ -23,6 +25,9 @@ class MCSymbol;
|
|||||||
/// form, this can hold "SymbolA - SymbolB + imm64". Not all targets supports
|
/// form, this can hold "SymbolA - SymbolB + imm64". Not all targets supports
|
||||||
/// relocations of this general form, but we need to represent this anyway.
|
/// relocations of this general form, but we need to represent this anyway.
|
||||||
///
|
///
|
||||||
|
/// In the general form, SymbolB can only be defined if SymbolA is, and both
|
||||||
|
/// must be in the same (non-external) section.
|
||||||
|
///
|
||||||
/// Note that this class must remain a simple POD value class, because we need
|
/// Note that this class must remain a simple POD value class, because we need
|
||||||
/// it to live in unions etc.
|
/// it to live in unions etc.
|
||||||
class MCValue {
|
class MCValue {
|
||||||
@@ -35,9 +40,21 @@ public:
|
|||||||
MCSymbol *getSymB() const { return SymB; }
|
MCSymbol *getSymB() const { return SymB; }
|
||||||
|
|
||||||
bool isConstant() const { return !SymA && !SymB; }
|
bool isConstant() const { return !SymA && !SymB; }
|
||||||
|
|
||||||
|
/// getAssociatedSection - For relocatable values, return the section the
|
||||||
|
/// value is associated with.
|
||||||
|
///
|
||||||
|
/// @result - The value's associated section, or null for external or constant
|
||||||
|
/// values.
|
||||||
|
MCSection *getAssociatedSection() const {
|
||||||
|
return SymA ? SymA->getSection() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static MCValue get(MCSymbol *SymA, MCSymbol *SymB = 0, int64_t Val = 0) {
|
static MCValue get(MCSymbol *SymA, MCSymbol *SymB = 0, int64_t Val = 0) {
|
||||||
MCValue R;
|
MCValue R;
|
||||||
|
assert((!SymB || (SymA && SymA->getSection() &&
|
||||||
|
SymA->getSection() == SymB->getSection())) &&
|
||||||
|
"Invalid relocatable MCValue!");
|
||||||
R.Cst = Val;
|
R.Cst = Val;
|
||||||
R.SymA = SymA;
|
R.SymA = SymA;
|
||||||
R.SymB = SymB;
|
R.SymB = SymB;
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "AsmExpr.h"
|
#include "AsmExpr.h"
|
||||||
#include "llvm/MC/MCContext.h"
|
#include "llvm/MC/MCContext.h"
|
||||||
|
#include "llvm/MC/MCSymbol.h"
|
||||||
#include "llvm/MC/MCValue.h"
|
#include "llvm/MC/MCValue.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@@ -16,38 +17,61 @@ AsmExpr::~AsmExpr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
|
bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
|
||||||
|
MCValue Value;
|
||||||
|
|
||||||
|
if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isConstant())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Res = Value.getConstant();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsmExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
|
||||||
switch (getKind()) {
|
switch (getKind()) {
|
||||||
default:
|
default:
|
||||||
assert(0 && "Invalid assembly expression kind!");
|
assert(0 && "Invalid assembly expression kind!");
|
||||||
|
|
||||||
case Constant:
|
case Constant:
|
||||||
Res = cast<AsmConstantExpr>(this)->getValue();
|
Res = MCValue::get(cast<AsmConstantExpr>(this)->getValue());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case SymbolRef: {
|
case SymbolRef: {
|
||||||
MCSymbol *Sym = cast<AsmSymbolRefExpr>(this)->getSymbol();
|
MCSymbol *Sym = cast<AsmSymbolRefExpr>(this)->getSymbol();
|
||||||
const MCValue *Value = Ctx.GetSymbolValue(Sym);
|
if (const MCValue *Value = Ctx.GetSymbolValue(Sym))
|
||||||
|
Res = *Value;
|
||||||
// FIXME: Return more information about the failure.
|
else
|
||||||
if (!Value || !Value->isConstant())
|
Res = MCValue::get(Sym, 0, 0);
|
||||||
return false;
|
|
||||||
|
|
||||||
Res = Value->getConstant();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Unary: {
|
case Unary: {
|
||||||
const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this);
|
const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this);
|
||||||
int64_t Value;
|
MCValue Value;
|
||||||
|
|
||||||
if (!AUE->getSubExpr()->EvaluateAsAbsolute(Ctx, Value))
|
if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (AUE->getOpcode()) {
|
switch (AUE->getOpcode()) {
|
||||||
case AsmUnaryExpr::LNot: Res = !Value; break;
|
case AsmUnaryExpr::LNot:
|
||||||
case AsmUnaryExpr::Minus: Res = -Value; break;
|
if (!Value.isConstant())
|
||||||
case AsmUnaryExpr::Not: Res = ~Value; break;
|
return false;
|
||||||
case AsmUnaryExpr::Plus: Res = +Value; break;
|
Res = MCValue::get(!Value.getConstant());
|
||||||
|
break;
|
||||||
|
case AsmUnaryExpr::Minus:
|
||||||
|
/// -(a - b + const) ==> (b - a - const)
|
||||||
|
if (Value.getSymA() && !Value.getSymA())
|
||||||
|
return false;
|
||||||
|
Res = MCValue::get(Value.getSymB(), Value.getSymA(),
|
||||||
|
-Value.getConstant());
|
||||||
|
break;
|
||||||
|
case AsmUnaryExpr::Not:
|
||||||
|
if (!Value.isConstant())
|
||||||
|
return false;
|
||||||
|
Res = MCValue::get(~Value.getConstant());
|
||||||
|
break;
|
||||||
|
case AsmUnaryExpr::Plus:
|
||||||
|
Res = Value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -55,36 +79,75 @@ bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
|
|||||||
|
|
||||||
case Binary: {
|
case Binary: {
|
||||||
const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this);
|
const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this);
|
||||||
int64_t LHS, RHS;
|
MCValue LHSValue, RHSValue;
|
||||||
|
|
||||||
if (!ABE->getLHS()->EvaluateAsAbsolute(Ctx, LHS) ||
|
if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
|
||||||
!ABE->getRHS()->EvaluateAsAbsolute(Ctx, RHS))
|
!ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// We only support a few operations on non-constant expressions, handle
|
||||||
|
// those first.
|
||||||
|
if (!LHSValue.isConstant() || !RHSValue.isConstant()) {
|
||||||
|
switch (ABE->getOpcode()) {
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
case AsmBinaryExpr::Sub:
|
||||||
|
// Negate RHS and fall through.
|
||||||
|
RHSValue = MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(),
|
||||||
|
-RHSValue.getConstant());
|
||||||
|
case AsmBinaryExpr::Add:
|
||||||
|
// (a_0 - b_0 + cst_0) + (a_1 - b_1 + cst_1)
|
||||||
|
|
||||||
|
// We can't add or subtract two symbols.
|
||||||
|
if ((LHSValue.getSymA() && RHSValue.getSymB()) ||
|
||||||
|
(LHSValue.getSymB() && RHSValue.getSymB()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MCSymbol *A =
|
||||||
|
LHSValue.getSymA() ? LHSValue.getSymA() : RHSValue.getSymA();
|
||||||
|
MCSymbol *B =
|
||||||
|
LHSValue.getSymB() ? LHSValue.getSymB() : RHSValue.getSymB();
|
||||||
|
if (B) {
|
||||||
|
// If we have a negated symbol, then we must have also have a
|
||||||
|
// non-negated symbol, and both symbols must be in the same
|
||||||
|
// non-external section. We can do this check later to permit
|
||||||
|
// expressions which eventually fold to a representable form -- such
|
||||||
|
// as (a + (0 - b)) -- if necessary.
|
||||||
|
if (!A || !A->getSection() || A->getSection() != B->getSection())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Res = MCValue::get(A, B,
|
||||||
|
LHSValue.getConstant() + RHSValue.getConstant());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: We need target hooks for the evaluation. It may be limited in
|
// FIXME: We need target hooks for the evaluation. It may be limited in
|
||||||
// width, and gas defines the result of comparisons differently from Apple
|
// width, and gas defines the result of comparisons differently from Apple
|
||||||
// as (the result is sign extended).
|
// as (the result is sign extended).
|
||||||
|
int64_t Result, LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
|
||||||
switch (ABE->getOpcode()) {
|
switch (ABE->getOpcode()) {
|
||||||
case AsmBinaryExpr::Add: Res = LHS + RHS; break;
|
case AsmBinaryExpr::Add: Result = LHS + RHS; break;
|
||||||
case AsmBinaryExpr::And: Res = LHS & RHS; break;
|
case AsmBinaryExpr::And: Result = LHS & RHS; break;
|
||||||
case AsmBinaryExpr::Div: Res = LHS / RHS; break;
|
case AsmBinaryExpr::Div: Result = LHS / RHS; break;
|
||||||
case AsmBinaryExpr::EQ: Res = LHS == RHS; break;
|
case AsmBinaryExpr::EQ: Result = LHS == RHS; break;
|
||||||
case AsmBinaryExpr::GT: Res = LHS > RHS; break;
|
case AsmBinaryExpr::GT: Result = LHS > RHS; break;
|
||||||
case AsmBinaryExpr::GTE: Res = LHS >= RHS; break;
|
case AsmBinaryExpr::GTE: Result = LHS >= RHS; break;
|
||||||
case AsmBinaryExpr::LAnd: Res = LHS && RHS; break;
|
case AsmBinaryExpr::LAnd: Result = LHS && RHS; break;
|
||||||
case AsmBinaryExpr::LOr: Res = LHS || RHS; break;
|
case AsmBinaryExpr::LOr: Result = LHS || RHS; break;
|
||||||
case AsmBinaryExpr::LT: Res = LHS < RHS; break;
|
case AsmBinaryExpr::LT: Result = LHS < RHS; break;
|
||||||
case AsmBinaryExpr::LTE: Res = LHS <= RHS; break;
|
case AsmBinaryExpr::LTE: Result = LHS <= RHS; break;
|
||||||
case AsmBinaryExpr::Mod: Res = LHS % RHS; break;
|
case AsmBinaryExpr::Mod: Result = LHS % RHS; break;
|
||||||
case AsmBinaryExpr::Mul: Res = LHS * RHS; break;
|
case AsmBinaryExpr::Mul: Result = LHS * RHS; break;
|
||||||
case AsmBinaryExpr::NE: Res = LHS != RHS; break;
|
case AsmBinaryExpr::NE: Result = LHS != RHS; break;
|
||||||
case AsmBinaryExpr::Or: Res = LHS | RHS; break;
|
case AsmBinaryExpr::Or: Result = LHS | RHS; break;
|
||||||
case AsmBinaryExpr::Shl: Res = LHS << RHS; break;
|
case AsmBinaryExpr::Shl: Result = LHS << RHS; break;
|
||||||
case AsmBinaryExpr::Shr: Res = LHS >> RHS; break;
|
case AsmBinaryExpr::Shr: Result = LHS >> RHS; break;
|
||||||
case AsmBinaryExpr::Sub: Res = LHS - RHS; break;
|
case AsmBinaryExpr::Sub: Result = LHS - RHS; break;
|
||||||
case AsmBinaryExpr::Xor: Res = LHS ^ RHS; break;
|
case AsmBinaryExpr::Xor: Result = LHS ^ RHS; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Res = MCValue::get(Result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
class MCContext;
|
class MCContext;
|
||||||
class MCSymbol;
|
class MCSymbol;
|
||||||
|
class MCValue;
|
||||||
|
|
||||||
class AsmExpr {
|
class AsmExpr {
|
||||||
public:
|
public:
|
||||||
@@ -39,10 +40,17 @@ public:
|
|||||||
|
|
||||||
/// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value.
|
/// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value.
|
||||||
///
|
///
|
||||||
/// @param Res - The absolute value if evaluation succeeds.
|
/// @param Res - The absolute value, if evaluation succeeds.
|
||||||
/// @result - True on success.
|
/// @result - True on success.
|
||||||
bool EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const;
|
bool EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const;
|
||||||
|
|
||||||
|
/// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable
|
||||||
|
/// value.
|
||||||
|
///
|
||||||
|
/// @param Res - The relocatable value, if evaluation succeeds.
|
||||||
|
/// @result - True on success.
|
||||||
|
bool EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const;
|
||||||
|
|
||||||
static bool classof(const AsmExpr *) { return true; }
|
static bool classof(const AsmExpr *) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -153,6 +153,18 @@ bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AsmParser::ParseRelocatableExpression(MCValue &Res) {
|
||||||
|
AsmExpr *Expr;
|
||||||
|
|
||||||
|
if (ParseExpression(Expr))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!Expr->EvaluateAsRelocatable(Ctx, Res))
|
||||||
|
return TokError("expected relocatable expression");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned getBinOpPrecedence(asmtok::TokKind K,
|
static unsigned getBinOpPrecedence(asmtok::TokKind K,
|
||||||
AsmBinaryExpr::Opcode &Kind) {
|
AsmBinaryExpr::Opcode &Kind) {
|
||||||
switch (K) {
|
switch (K) {
|
||||||
|
@@ -22,7 +22,8 @@ class AsmExpr;
|
|||||||
class MCContext;
|
class MCContext;
|
||||||
class MCInst;
|
class MCInst;
|
||||||
class MCStreamer;
|
class MCStreamer;
|
||||||
|
class MCValue;
|
||||||
|
|
||||||
class AsmParser {
|
class AsmParser {
|
||||||
AsmLexer Lexer;
|
AsmLexer Lexer;
|
||||||
MCContext &Ctx;
|
MCContext &Ctx;
|
||||||
@@ -53,15 +54,23 @@ private:
|
|||||||
/// @param Res - The resulting expression. The pointer value is null on error.
|
/// @param Res - The resulting expression. The pointer value is null on error.
|
||||||
/// @result - False on success.
|
/// @result - False on success.
|
||||||
bool ParseExpression(AsmExpr *&Res);
|
bool ParseExpression(AsmExpr *&Res);
|
||||||
|
|
||||||
/// ParseAbsoluteExpr - Parse an expression which must evaluate to an absolute
|
/// ParseAbsoluteExpression - Parse an expression which must evaluate to an
|
||||||
/// value.
|
/// absolute value.
|
||||||
///
|
///
|
||||||
/// @param Res - The value of the absolute expression. The result is undefined
|
/// @param Res - The value of the absolute expression. The result is undefined
|
||||||
/// on error.
|
/// on error.
|
||||||
/// @result - False on success.
|
/// @result - False on success.
|
||||||
bool ParseAbsoluteExpression(int64_t &Res);
|
bool ParseAbsoluteExpression(int64_t &Res);
|
||||||
|
|
||||||
|
/// ParseRelocatableExpression - Parse an expression which must be
|
||||||
|
/// relocatable.
|
||||||
|
///
|
||||||
|
/// @param Res - The relocatable expression value. The result is undefined on
|
||||||
|
/// error.
|
||||||
|
/// @result - False on success.
|
||||||
|
bool ParseRelocatableExpression(MCValue &Res);
|
||||||
|
|
||||||
bool ParsePrimaryExpr(AsmExpr *&Res);
|
bool ParsePrimaryExpr(AsmExpr *&Res);
|
||||||
bool ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res);
|
bool ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res);
|
||||||
bool ParseParenExpr(AsmExpr *&Res);
|
bool ParseParenExpr(AsmExpr *&Res);
|
||||||
|
Reference in New Issue
Block a user