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);
|
||||
virtual ~MCTargetStreamer();
|
||||
|
||||
const MCStreamer &getStreamer() { return Streamer; }
|
||||
MCStreamer &getStreamer() { return Streamer; }
|
||||
|
||||
// Allow a target to add behavior to the EmitLabel of MCStreamer.
|
||||
virtual void emitLabel(MCSymbol *Symbol);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "llvm/MC/MCParser/AsmCond.h"
|
||||
#include "llvm/MC/MCParser/AsmLexer.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParserUtils.h"
|
||||
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
@ -2178,82 +2179,20 @@ void AsmParser::handleMacroExit() {
|
||||
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 NoDeadStrip) {
|
||||
// FIXME: Use better location, we should use proper tokens.
|
||||
SMLoc EqualLoc = Lexer.getLoc();
|
||||
|
||||
MCSymbol *Sym;
|
||||
const MCExpr *Value;
|
||||
if (parseExpression(Value))
|
||||
if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
|
||||
Value))
|
||||
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 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();
|
||||
}
|
||||
if (!Sym) {
|
||||
// In the case where we parse an expression starting with a '.', we will
|
||||
// not generate an error, nor will we create a symbol. In this case we
|
||||
// should just return out.
|
||||
return false;
|
||||
} else
|
||||
Sym = getContext().getOrCreateSymbol(Name);
|
||||
|
||||
Sym->setRedefinable(allow_redef);
|
||||
}
|
||||
|
||||
// Do the assignment.
|
||||
Out.EmitAssignment(Sym, Value);
|
||||
@ -4777,6 +4716,103 @@ bool AsmParser::parseMSInlineAsm(
|
||||
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.
|
||||
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
|
||||
MCStreamer &Out, const MCAsmInfo &MAI) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "llvm/MC/MCObjectFileInfo.h"
|
||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParserUtils.h"
|
||||
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
@ -9887,22 +9888,13 @@ bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) {
|
||||
}
|
||||
Lex();
|
||||
|
||||
MCSymbol *Sym;
|
||||
const MCExpr *Value;
|
||||
if (Parser.parseExpression(Value)) {
|
||||
TokError("missing expression");
|
||||
Parser.eatToEndOfStatement();
|
||||
return false;
|
||||
}
|
||||
if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
|
||||
Parser, Sym, Value))
|
||||
return true;
|
||||
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||
TokError("unexpected token");
|
||||
Parser.eatToEndOfStatement();
|
||||
return false;
|
||||
}
|
||||
Lex();
|
||||
|
||||
MCSymbol *Alias = getContext().getOrCreateSymbol(Name);
|
||||
getTargetStreamer().emitThumbSet(Alias, Value);
|
||||
getTargetStreamer().emitThumbSet(Sym, Value);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -41,3 +41,31 @@
|
||||
@ CHECK: .thumb_set trailer_trash, 0x11fe1e55,
|
||||
@ 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
|
||||
|
||||
.type beta,%function
|
||||
beta:
|
||||
bkpt
|
||||
|
||||
.thumb_set beta, alpha
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user