1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

Implement Paste

Add a paste operator '#' to take two identifier-like strings and joint
them.  Internally paste gets represented as a !strconcat() with any
necessary casts to string added.

This will be used to implement basic for loop functionality as in:

for i = [0, 1, 2, 3, 4, 5, 6, 7] {
  def R#i : Register<...>
}

llvm-svn: 142525
This commit is contained in:
David Greene 2011-10-19 13:04:43 +00:00
parent 82113dc5a1
commit d5d61b6c0c
3 changed files with 67 additions and 28 deletions

View File

@ -91,10 +91,10 @@ tgtok::TokKind TGLexer::LexToken() {
switch (CurChar) {
default:
// Handle letters: [a-zA-Z_#]
if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
// Handle letters: [a-zA-Z_]
if (isalpha(CurChar) || CurChar == '_')
return LexIdentifier();
// Unknown character, emit an error.
return ReturnError(TokStart, "Unexpected character");
case EOF: return tgtok::Eof;
@ -111,6 +111,7 @@ tgtok::TokKind TGLexer::LexToken() {
case ')': return tgtok::r_paren;
case '=': return tgtok::equal;
case '?': return tgtok::question;
case '#': return tgtok::paste;
case 0:
case ' ':
@ -250,8 +251,7 @@ tgtok::TokKind TGLexer::LexIdentifier() {
const char *IdentStart = TokStart;
// Match the rest of the identifier regex: [0-9a-zA-Z_#]*
while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' ||
*CurPtr == '#')
while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
++CurPtr;
// Check to see if this identifier is a keyword.

View File

@ -39,7 +39,8 @@ namespace tgtok {
colon, semi, // : ;
comma, period, // , .
equal, question, // = ?
paste, // #
// Keywords.
Bit, Bits, Class, Code, Dag, Def, Defm, Field, In, Int, Let, List,
MultiClass, String,

View File

@ -1083,6 +1083,12 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
Init *R = 0;
switch (Lex.getCode()) {
default: TokError("Unknown token when parsing a value"); break;
case tgtok::paste:
// This is a leading paste operation. This is deprecated but
// still exists in some .td files. Ignore it.
Lex.Lex(); // Skip '#'.
return ParseSimpleValue(CurRec, ItemType, Mode);
break;
case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break;
case tgtok::StrVal: {
std::string Val = Lex.getCurStrVal();
@ -1410,6 +1416,56 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
Result = FieldInit::get(Result, Lex.getCurStrVal());
Lex.Lex(); // eat field name
break;
case tgtok::paste:
SMLoc PasteLoc = Lex.getLoc();
// Create a !strconcat() operation, first casting each operand to
// a string if necessary.
TypedInit *LHS = dynamic_cast<TypedInit *>(Result);
if (!LHS) {
Error(PasteLoc, "LHS of paste is not typed!");
return 0;
}
if (LHS->getType() != StringRecTy::get()) {
LHS = UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get());
}
TypedInit *RHS = 0;
Lex.Lex(); // Eat the '#'.
switch (Lex.getCode()) {
case tgtok::colon:
case tgtok::semi:
case tgtok::l_brace:
// These are all of the tokens that can begin an object body.
// Some of these can also begin values but we disallow those cases
// because they are unlikely to be useful.
// Trailing paste, concat with an empty string.
RHS = StringInit::get("");
break;
default:
Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode);
RHS = dynamic_cast<TypedInit *>(RHSResult);
if (!RHS) {
Error(PasteLoc, "RHS of paste is not typed!");
return 0;
}
if (RHS->getType() != StringRecTy::get()) {
RHS = UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get());
}
break;
}
Result = BinOpInit::get(BinOpInit::STRCONCAT, LHS, RHS,
StringRecTy::get())->Fold(CurRec, CurMultiClass);
break;
}
}
}
@ -1979,41 +2035,23 @@ InstantiateMulticlassDef(MultiClass &MC,
// instantiated def a unique name. Otherwise, if "#NAME#" exists in the
// name, substitute the prefix for #NAME#. Otherwise, use the defm name
// as a prefix.
StringInit *DefNameString =
dynamic_cast<StringInit *>(DefProto->getNameInit());
if (DefNameString == 0) {
Error(DefmPrefixLoc, "Def name is not a string");
return 0;
}
if (DefmPrefix == 0)
DefmPrefix = StringInit::get(GetNewAnonymousName());
Init *DefName = DefProto->getNameInit();
// See if we can substitute #NAME#.
Init *NewDefName =
TernOpInit::get(TernOpInit::SUBST,
StringInit::get("#NAME#"),
DefmPrefix,
DefName,
StringRecTy::get())->Fold(DefProto, &MC);
if (NewDefName == DefName) {
// We did't do any substitution. We should concatenate the given
// prefix and name.
if (DefmPrefix == 0)
DefmPrefix = StringInit::get(GetNewAnonymousName());
StringInit *DefNameString = dynamic_cast<StringInit *>(DefName);
if (DefNameString != 0) {
// We have a fully expanded string so there are no operators to
// resolve. We should concatenate the given prefix and name.
DefName =
BinOpInit::get(BinOpInit::STRCONCAT,
UnOpInit::get(UnOpInit::CAST, DefmPrefix,
StringRecTy::get())->Fold(DefProto, &MC),
DefName, StringRecTy::get())->Fold(DefProto, &MC);
}
else
DefName = NewDefName;
Record *CurRec = new Record(DefName, DefmPrefixLoc, Records);