mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
Change .thumb_set to have the same error checks as .set.
According to the documentation, .thumb_set is 'the equivalent of a .set directive'. We didn't have equivalent behaviour in terms of all the errors we could throw, for example, when a symbol is redefined. This change refactors parseAssignment so that it can be used by .set and .thumb_set and implements tests for .thumb_set for all the errors thrown by that method. Reviewed by Rafael Espíndola. llvm-svn: 240318
This commit is contained in:
parent
1ffe9ef119
commit
e49cb88496
27
include/llvm/MC/MCParser/MCAsmParserUtils.h
Normal file
27
include/llvm/MC/MCParser/MCAsmParserUtils.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//===------ llvm/MC/MCAsmParserUtils.h - Asm Parser Utilities ---*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_MC_MCPARSER_MCASMPARSERUTILS_H
|
||||||
|
#define LLVM_MC_MCPARSER_MCASMPARSERUTILS_H
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace MCParserUtils {
|
||||||
|
|
||||||
|
/// Parse a value expression and return whether it can be assigned to a symbol
|
||||||
|
/// with the given name.
|
||||||
|
///
|
||||||
|
/// On success, returns false and sets the Symbol and Value output parameters.
|
||||||
|
bool parseAssignmentExpression(StringRef Name, bool allow_redef,
|
||||||
|
MCAsmParser &Parser, MCSymbol *&Symbol,
|
||||||
|
const MCExpr *&Value);
|
||||||
|
|
||||||
|
} // namespace MCParserUtils
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
#endif
|
@ -78,7 +78,7 @@ public:
|
|||||||
MCTargetStreamer(MCStreamer &S);
|
MCTargetStreamer(MCStreamer &S);
|
||||||
virtual ~MCTargetStreamer();
|
virtual ~MCTargetStreamer();
|
||||||
|
|
||||||
const MCStreamer &getStreamer() { return Streamer; }
|
MCStreamer &getStreamer() { return Streamer; }
|
||||||
|
|
||||||
// Allow a target to add behavior to the EmitLabel of MCStreamer.
|
// Allow a target to add behavior to the EmitLabel of MCStreamer.
|
||||||
virtual void emitLabel(MCSymbol *Symbol);
|
virtual void emitLabel(MCSymbol *Symbol);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "llvm/MC/MCParser/AsmCond.h"
|
#include "llvm/MC/MCParser/AsmCond.h"
|
||||||
#include "llvm/MC/MCParser/AsmLexer.h"
|
#include "llvm/MC/MCParser/AsmLexer.h"
|
||||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||||
|
#include "llvm/MC/MCParser/MCAsmParserUtils.h"
|
||||||
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
||||||
#include "llvm/MC/MCRegisterInfo.h"
|
#include "llvm/MC/MCRegisterInfo.h"
|
||||||
#include "llvm/MC/MCSectionMachO.h"
|
#include "llvm/MC/MCSectionMachO.h"
|
||||||
@ -2178,82 +2179,20 @@ void AsmParser::handleMacroExit() {
|
|||||||
ActiveMacros.pop_back();
|
ActiveMacros.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isUsedIn(const MCSymbol *Sym, const MCExpr *Value) {
|
|
||||||
switch (Value->getKind()) {
|
|
||||||
case MCExpr::Binary: {
|
|
||||||
const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
|
|
||||||
return isUsedIn(Sym, BE->getLHS()) || isUsedIn(Sym, BE->getRHS());
|
|
||||||
}
|
|
||||||
case MCExpr::Target:
|
|
||||||
case MCExpr::Constant:
|
|
||||||
return false;
|
|
||||||
case MCExpr::SymbolRef: {
|
|
||||||
const MCSymbol &S =
|
|
||||||
static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
|
|
||||||
if (S.isVariable())
|
|
||||||
return isUsedIn(Sym, S.getVariableValue());
|
|
||||||
return &S == Sym;
|
|
||||||
}
|
|
||||||
case MCExpr::Unary:
|
|
||||||
return isUsedIn(Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm_unreachable("Unknown expr kind!");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
|
bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
|
||||||
bool NoDeadStrip) {
|
bool NoDeadStrip) {
|
||||||
// FIXME: Use better location, we should use proper tokens.
|
MCSymbol *Sym;
|
||||||
SMLoc EqualLoc = Lexer.getLoc();
|
|
||||||
|
|
||||||
const MCExpr *Value;
|
const MCExpr *Value;
|
||||||
if (parseExpression(Value))
|
if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
|
||||||
|
Value))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Note: we don't count b as used in "a = b". This is to allow
|
if (!Sym) {
|
||||||
// a = b
|
// In the case where we parse an expression starting with a '.', we will
|
||||||
// b = c
|
// not generate an error, nor will we create a symbol. In this case we
|
||||||
|
// should just return out.
|
||||||
if (Lexer.isNot(AsmToken::EndOfStatement))
|
|
||||||
return TokError("unexpected token in assignment");
|
|
||||||
|
|
||||||
// Eat the end of statement marker.
|
|
||||||
Lex();
|
|
||||||
|
|
||||||
// Validate that the LHS is allowed to be a variable (either it has not been
|
|
||||||
// used as a symbol, or it is an absolute symbol).
|
|
||||||
MCSymbol *Sym = getContext().lookupSymbol(Name);
|
|
||||||
if (Sym) {
|
|
||||||
// Diagnose assignment to a label.
|
|
||||||
//
|
|
||||||
// FIXME: Diagnostics. Note the location of the definition as a label.
|
|
||||||
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
|
|
||||||
if (isUsedIn(Sym, Value))
|
|
||||||
return Error(EqualLoc, "Recursive use of '" + Name + "'");
|
|
||||||
else if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable())
|
|
||||||
; // Allow redefinitions of undefined symbols only used in directives.
|
|
||||||
else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
|
|
||||||
; // Allow redefinitions of variables that haven't yet been used.
|
|
||||||
else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
|
|
||||||
return Error(EqualLoc, "redefinition of '" + Name + "'");
|
|
||||||
else if (!Sym->isVariable())
|
|
||||||
return Error(EqualLoc, "invalid assignment to '" + Name + "'");
|
|
||||||
else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
|
|
||||||
return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
|
|
||||||
Name + "'");
|
|
||||||
|
|
||||||
// Don't count these checks as uses.
|
|
||||||
Sym->setUsed(false);
|
|
||||||
} else if (Name == ".") {
|
|
||||||
if (Out.EmitValueToOffset(Value, 0)) {
|
|
||||||
Error(EqualLoc, "expected absolute expression");
|
|
||||||
eatToEndOfStatement();
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
} else
|
}
|
||||||
Sym = getContext().getOrCreateSymbol(Name);
|
|
||||||
|
|
||||||
Sym->setRedefinable(allow_redef);
|
|
||||||
|
|
||||||
// Do the assignment.
|
// Do the assignment.
|
||||||
Out.EmitAssignment(Sym, Value);
|
Out.EmitAssignment(Sym, Value);
|
||||||
@ -4777,6 +4716,103 @@ bool AsmParser::parseMSInlineAsm(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace MCParserUtils {
|
||||||
|
|
||||||
|
/// Returns whether the given symbol is used anywhere in the given expression,
|
||||||
|
/// or subexpressions.
|
||||||
|
static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
|
||||||
|
switch (Value->getKind()) {
|
||||||
|
case MCExpr::Binary: {
|
||||||
|
const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
|
||||||
|
return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
|
||||||
|
isSymbolUsedInExpression(Sym, BE->getRHS());
|
||||||
|
}
|
||||||
|
case MCExpr::Target:
|
||||||
|
case MCExpr::Constant:
|
||||||
|
return false;
|
||||||
|
case MCExpr::SymbolRef: {
|
||||||
|
const MCSymbol &S =
|
||||||
|
static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
|
||||||
|
if (S.isVariable())
|
||||||
|
return isSymbolUsedInExpression(Sym, S.getVariableValue());
|
||||||
|
return &S == Sym;
|
||||||
|
}
|
||||||
|
case MCExpr::Unary:
|
||||||
|
return isSymbolUsedInExpression(
|
||||||
|
Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_unreachable("Unknown expr kind!");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseAssignmentExpression(StringRef Name, bool allow_redef,
|
||||||
|
MCAsmParser &Parser, MCSymbol *&Sym,
|
||||||
|
const MCExpr *&Value) {
|
||||||
|
MCAsmLexer &Lexer = Parser.getLexer();
|
||||||
|
|
||||||
|
// FIXME: Use better location, we should use proper tokens.
|
||||||
|
SMLoc EqualLoc = Lexer.getLoc();
|
||||||
|
|
||||||
|
if (Parser.parseExpression(Value)) {
|
||||||
|
Parser.TokError("missing expression");
|
||||||
|
Parser.eatToEndOfStatement();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: we don't count b as used in "a = b". This is to allow
|
||||||
|
// a = b
|
||||||
|
// b = c
|
||||||
|
|
||||||
|
if (Lexer.isNot(AsmToken::EndOfStatement))
|
||||||
|
return Parser.TokError("unexpected token in assignment");
|
||||||
|
|
||||||
|
// Eat the end of statement marker.
|
||||||
|
Parser.Lex();
|
||||||
|
|
||||||
|
// Validate that the LHS is allowed to be a variable (either it has not been
|
||||||
|
// used as a symbol, or it is an absolute symbol).
|
||||||
|
Sym = Parser.getContext().lookupSymbol(Name);
|
||||||
|
if (Sym) {
|
||||||
|
// Diagnose assignment to a label.
|
||||||
|
//
|
||||||
|
// FIXME: Diagnostics. Note the location of the definition as a label.
|
||||||
|
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
|
||||||
|
if (isSymbolUsedInExpression(Sym, Value))
|
||||||
|
return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
|
||||||
|
else if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable())
|
||||||
|
; // Allow redefinitions of undefined symbols only used in directives.
|
||||||
|
else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
|
||||||
|
; // Allow redefinitions of variables that haven't yet been used.
|
||||||
|
else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
|
||||||
|
return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
|
||||||
|
else if (!Sym->isVariable())
|
||||||
|
return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
|
||||||
|
else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
|
||||||
|
return Parser.Error(EqualLoc,
|
||||||
|
"invalid reassignment of non-absolute variable '" +
|
||||||
|
Name + "'");
|
||||||
|
|
||||||
|
// Don't count these checks as uses.
|
||||||
|
Sym->setUsed(false);
|
||||||
|
} else if (Name == ".") {
|
||||||
|
if (Parser.getStreamer().EmitValueToOffset(Value, 0)) {
|
||||||
|
Parser.Error(EqualLoc, "expected absolute expression");
|
||||||
|
Parser.eatToEndOfStatement();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
Sym = Parser.getContext().getOrCreateSymbol(Name);
|
||||||
|
|
||||||
|
Sym->setRedefinable(allow_redef);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MCParserUtils
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
/// \brief Create an MCAsmParser instance.
|
/// \brief Create an MCAsmParser instance.
|
||||||
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
|
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
|
||||||
MCStreamer &Out, const MCAsmInfo &MAI) {
|
MCStreamer &Out, const MCAsmInfo &MAI) {
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "llvm/MC/MCObjectFileInfo.h"
|
#include "llvm/MC/MCObjectFileInfo.h"
|
||||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||||
|
#include "llvm/MC/MCParser/MCAsmParserUtils.h"
|
||||||
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
||||||
#include "llvm/MC/MCRegisterInfo.h"
|
#include "llvm/MC/MCRegisterInfo.h"
|
||||||
#include "llvm/MC/MCSection.h"
|
#include "llvm/MC/MCSection.h"
|
||||||
@ -9887,22 +9888,13 @@ bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) {
|
|||||||
}
|
}
|
||||||
Lex();
|
Lex();
|
||||||
|
|
||||||
|
MCSymbol *Sym;
|
||||||
const MCExpr *Value;
|
const MCExpr *Value;
|
||||||
if (Parser.parseExpression(Value)) {
|
if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
|
||||||
TokError("missing expression");
|
Parser, Sym, Value))
|
||||||
Parser.eatToEndOfStatement();
|
return true;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
getTargetStreamer().emitThumbSet(Sym, Value);
|
||||||
TokError("unexpected token");
|
|
||||||
Parser.eatToEndOfStatement();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Lex();
|
|
||||||
|
|
||||||
MCSymbol *Alias = getContext().getOrCreateSymbol(Name);
|
|
||||||
getTargetStreamer().emitThumbSet(Alias, Value);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,3 +41,31 @@
|
|||||||
@ CHECK: .thumb_set trailer_trash, 0x11fe1e55,
|
@ CHECK: .thumb_set trailer_trash, 0x11fe1e55,
|
||||||
@ CHECK: ^
|
@ CHECK: ^
|
||||||
|
|
||||||
|
.type alpha,%function
|
||||||
|
alpha:
|
||||||
|
nop
|
||||||
|
|
||||||
|
.type beta,%function
|
||||||
|
beta:
|
||||||
|
bkpt
|
||||||
|
|
||||||
|
.thumb_set beta, alpha
|
||||||
|
|
||||||
|
@ CHECK: error: redefinition of 'beta'
|
||||||
|
@ CHECK: .thumb_set beta, alpha
|
||||||
|
@ CHECK: ^
|
||||||
|
|
||||||
|
.type recursive_use,%function
|
||||||
|
.thumb_set recursive_use, recursive_use + 1
|
||||||
|
|
||||||
|
@ CHECK: error: Recursive use of 'recursive_use'
|
||||||
|
@ CHECK: .thumb_set recursive_use, recursive_use + 1
|
||||||
|
@ CHECK: ^
|
||||||
|
|
||||||
|
variable_result = alpha + 1
|
||||||
|
.long variable_result
|
||||||
|
.thumb_set variable_result, 1
|
||||||
|
|
||||||
|
@ CHECK: error: invalid reassignment of non-absolute variable 'variable_result'
|
||||||
|
@ CHECK: .thumb_set variable_result, 1
|
||||||
|
@ CHECK: ^
|
@ -54,8 +54,6 @@ alpha:
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
.type beta,%function
|
.type beta,%function
|
||||||
beta:
|
|
||||||
bkpt
|
|
||||||
|
|
||||||
.thumb_set beta, alpha
|
.thumb_set beta, alpha
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user