mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 05:00:26 +00:00
Added Mac OS X assembler style conditional assembly. I may come back and see if
I can clean this up a bit more and do way with the TheCondState and just use the top element on the TheCondStack if not empty. Also may tweak the code around ParseConditionalAssemblyDirectives() to simplify the AsmParser code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78423 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b124be4f97
commit
c114ed711e
12
test/MC/AsmParser/conditional_asm.s
Normal file
12
test/MC/AsmParser/conditional_asm.s
Normal file
@ -0,0 +1,12 @@
|
||||
# RUN: llvm-mc -triple i386-unknown-unknown %s -I %p | FileCheck %s
|
||||
|
||||
# CHECK: .byte 2
|
||||
.if 1+2
|
||||
.if 1-1
|
||||
.byte 1
|
||||
.elseif 2+2
|
||||
.byte 1+1
|
||||
.else
|
||||
.byte 0
|
||||
.endif
|
||||
.endif
|
38
tools/llvm-mc/AsmCond.h
Normal file
38
tools/llvm-mc/AsmCond.h
Normal file
@ -0,0 +1,38 @@
|
||||
//===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASMCOND_H
|
||||
#define ASMCOND_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// AsmCond - Class to support conditional assembly
|
||||
///
|
||||
/// The conditional assembly feature (.if, .else, .elseif and .endif) is
|
||||
/// implemented with AsmCond that tells us what we are in the middle of
|
||||
/// processing. Ignore can be either true or false. When true we are ignoring
|
||||
/// the block of code in the middle of a conditional.
|
||||
|
||||
class AsmCond {
|
||||
public:
|
||||
enum ConditionalAssemblyType {
|
||||
NoCond, // no conditional is being processed
|
||||
IfCond, // inside if conditional
|
||||
ElseIfCond, // inside elseif conditional
|
||||
ElseCond // inside else conditional
|
||||
};
|
||||
|
||||
ConditionalAssemblyType TheCond;
|
||||
bool CondMet;
|
||||
bool Ignore;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -45,18 +45,62 @@ bool AsmParser::Run() {
|
||||
|
||||
bool HadError = false;
|
||||
|
||||
AsmCond StartingCondState = TheCondState;
|
||||
|
||||
// While we have input, parse each statement.
|
||||
while (Lexer.isNot(AsmToken::Eof)) {
|
||||
// Handle conditional assembly here before calling ParseStatement()
|
||||
if (Lexer.getKind() == AsmToken::Identifier) {
|
||||
// If we have an identifier, handle it as the key symbol.
|
||||
AsmToken ID = Lexer.getTok();
|
||||
SMLoc IDLoc = ID.getLoc();
|
||||
StringRef IDVal = ID.getString();
|
||||
|
||||
if (IDVal == ".if" ||
|
||||
IDVal == ".elseif" ||
|
||||
IDVal == ".else" ||
|
||||
IDVal == ".endif") {
|
||||
if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc))
|
||||
continue;
|
||||
HadError = true;
|
||||
EatToEndOfStatement();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (TheCondState.Ignore) {
|
||||
EatToEndOfStatement();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ParseStatement()) continue;
|
||||
|
||||
// If we had an error, remember it and recover by skipping to the next line.
|
||||
// We had an error, remember it and recover by skipping to the next line.
|
||||
HadError = true;
|
||||
EatToEndOfStatement();
|
||||
}
|
||||
|
||||
if (TheCondState.TheCond != StartingCondState.TheCond ||
|
||||
TheCondState.Ignore != StartingCondState.Ignore)
|
||||
return TokError("unmatched .ifs or .elses");
|
||||
|
||||
return HadError;
|
||||
}
|
||||
|
||||
/// ParseConditionalAssemblyDirectives - parse the conditional assembly
|
||||
/// directives
|
||||
bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive,
|
||||
SMLoc DirectiveLoc) {
|
||||
if (Directive == ".if")
|
||||
return ParseDirectiveIf(DirectiveLoc);
|
||||
if (Directive == ".elseif")
|
||||
return ParseDirectiveElseIf(DirectiveLoc);
|
||||
if (Directive == ".else")
|
||||
return ParseDirectiveElse(DirectiveLoc);
|
||||
if (Directive == ".endif")
|
||||
return ParseDirectiveEndIf(DirectiveLoc);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
|
||||
void AsmParser::EatToEndOfStatement() {
|
||||
while (Lexer.isNot(AsmToken::EndOfStatement) &&
|
||||
@ -1264,3 +1308,116 @@ bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDirectiveIf
|
||||
/// ::= .if expression
|
||||
bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
|
||||
// Consume the identifier that was the .if directive
|
||||
Lexer.Lex();
|
||||
|
||||
TheCondStack.push_back(TheCondState);
|
||||
TheCondState.TheCond = AsmCond::IfCond;
|
||||
if(TheCondState.Ignore) {
|
||||
EatToEndOfStatement();
|
||||
}
|
||||
else {
|
||||
int64_t ExprValue;
|
||||
if (ParseAbsoluteExpression(ExprValue))
|
||||
return true;
|
||||
|
||||
if (Lexer.isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.if' directive");
|
||||
|
||||
Lexer.Lex();
|
||||
|
||||
TheCondState.CondMet = ExprValue;
|
||||
TheCondState.Ignore = !TheCondState.CondMet;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDirectiveElseIf
|
||||
/// ::= .elseif expression
|
||||
bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
|
||||
if (TheCondState.TheCond != AsmCond::IfCond &&
|
||||
TheCondState.TheCond != AsmCond::ElseIfCond)
|
||||
Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
|
||||
" an .elseif");
|
||||
TheCondState.TheCond = AsmCond::ElseIfCond;
|
||||
|
||||
// Consume the identifier that was the .elseif directive
|
||||
Lexer.Lex();
|
||||
|
||||
bool LastIgnoreState = false;
|
||||
if (!TheCondStack.empty())
|
||||
LastIgnoreState = TheCondStack.back().Ignore;
|
||||
if (LastIgnoreState || TheCondState.CondMet) {
|
||||
TheCondState.Ignore = true;
|
||||
EatToEndOfStatement();
|
||||
}
|
||||
else {
|
||||
int64_t ExprValue;
|
||||
if (ParseAbsoluteExpression(ExprValue))
|
||||
return true;
|
||||
|
||||
if (Lexer.isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.elseif' directive");
|
||||
|
||||
Lexer.Lex();
|
||||
TheCondState.CondMet = ExprValue;
|
||||
TheCondState.Ignore = !TheCondState.CondMet;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDirectiveElse
|
||||
/// ::= .else
|
||||
bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
|
||||
// Consume the identifier that was the .else directive
|
||||
Lexer.Lex();
|
||||
|
||||
if (Lexer.isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.else' directive");
|
||||
|
||||
Lexer.Lex();
|
||||
|
||||
if (TheCondState.TheCond != AsmCond::IfCond &&
|
||||
TheCondState.TheCond != AsmCond::ElseIfCond)
|
||||
Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
|
||||
".elseif");
|
||||
TheCondState.TheCond = AsmCond::ElseCond;
|
||||
bool LastIgnoreState = false;
|
||||
if (!TheCondStack.empty())
|
||||
LastIgnoreState = TheCondStack.back().Ignore;
|
||||
if (LastIgnoreState || TheCondState.CondMet)
|
||||
TheCondState.Ignore = true;
|
||||
else
|
||||
TheCondState.Ignore = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDirectiveEndIf
|
||||
/// ::= .endif
|
||||
bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
|
||||
// Consume the identifier that was the .endif directive
|
||||
Lexer.Lex();
|
||||
|
||||
if (Lexer.isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.endif' directive");
|
||||
|
||||
Lexer.Lex();
|
||||
|
||||
if ((TheCondState.TheCond == AsmCond::NoCond) ||
|
||||
TheCondStack.empty())
|
||||
Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
|
||||
".else");
|
||||
if (!TheCondStack.empty()) {
|
||||
TheCondState = TheCondStack.back();
|
||||
TheCondStack.pop_back();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -14,12 +14,15 @@
|
||||
#ifndef ASMPARSER_H
|
||||
#define ASMPARSER_H
|
||||
|
||||
#include <vector>
|
||||
#include "AsmLexer.h"
|
||||
#include "AsmCond.h"
|
||||
#include "llvm/MC/MCAsmParser.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
|
||||
namespace llvm {
|
||||
class AsmExpr;
|
||||
class AsmCond;
|
||||
class MCContext;
|
||||
class MCInst;
|
||||
class MCStreamer;
|
||||
@ -33,7 +36,10 @@ private:
|
||||
MCContext &Ctx;
|
||||
MCStreamer &Out;
|
||||
TargetAsmParser *TargetParser;
|
||||
|
||||
|
||||
AsmCond TheCondState;
|
||||
std::vector<AsmCond> TheCondStack;
|
||||
|
||||
public:
|
||||
AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out)
|
||||
: Lexer(_SM), Ctx(_Ctx), Out(_Out), TargetParser(0) {}
|
||||
@ -67,6 +73,8 @@ private:
|
||||
|
||||
bool TokError(const char *Msg);
|
||||
|
||||
bool ParseConditionalAssemblyDirectives(StringRef Directive,
|
||||
SMLoc DirectiveLoc);
|
||||
void EatToEndOfStatement();
|
||||
|
||||
bool ParseAssignment(const StringRef &Name, bool IsDotSet);
|
||||
@ -118,6 +126,12 @@ private:
|
||||
|
||||
bool ParseDirectiveAbort(); // ".abort"
|
||||
bool ParseDirectiveInclude(); // ".include"
|
||||
|
||||
bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if"
|
||||
bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
|
||||
bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else"
|
||||
bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
Loading…
Reference in New Issue
Block a user