Generalize the previous binary operator support and add a string concatenation

operation.  This implements Regression/TableGen/strconcat.td.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27312 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-03-31 21:53:49 +00:00
parent fd2ae97ac3
commit 711e5d96aa
4 changed files with 109 additions and 38 deletions

View File

@ -202,6 +202,7 @@ in { return IN; }
!sra { return SRATOK; }
!srl { return SRLTOK; }
!shl { return SHLTOK; }
!strconcat { return STRCONCATTOK; }
{Identifier} { Filelval.StrVal = new std::string(yytext, yytext+yyleng);

View File

@ -200,7 +200,7 @@ using namespace llvm;
};
%token INT BIT STRING BITS LIST CODE DAG CLASS DEF FIELD LET IN
%token SHLTOK SRATOK SRLTOK
%token SHLTOK SRATOK SRLTOK STRCONCATTOK
%token <IntVal> INTVAL
%token <StrVal> ID VARNAME STRVAL CODEFRAGMENT
@ -352,23 +352,13 @@ Value : IDValue {
}
delete $3;
} | SHLTOK '(' Value ',' Value ')' {
$$ = $3->getBinaryOp(Init::SHL, $5);
if ($$ == 0) {
err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
exit(1);
}
$$ = (new BinOpInit(BinOpInit::SHL, $3, $5))->Fold();
} | SRATOK '(' Value ',' Value ')' {
$$ = $3->getBinaryOp(Init::SRA, $5);
if ($$ == 0) {
err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
exit(1);
}
$$ = (new BinOpInit(BinOpInit::SRA, $3, $5))->Fold();
} | SRLTOK '(' Value ',' Value ')' {
$$ = $3->getBinaryOp(Init::SRL, $5);
if ($$ == 0) {
err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
exit(1);
}
$$ = (new BinOpInit(BinOpInit::SRL, $3, $5))->Fold();
} | STRCONCATTOK '(' Value ',' Value ')' {
$$ = (new BinOpInit(BinOpInit::STRCONCAT, $3, $5))->Fold();
};
OptVarName : /* empty */ {

View File

@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
// Implement the tablegen record classes.
//
//===----------------------------------------------------------------------===//
@ -125,6 +126,19 @@ Init *IntRecTy::convertValue(TypedInit *TI) {
return 0;
}
Init *StringRecTy::convertValue(BinOpInit *BO) {
if (BO->getOpcode() == BinOpInit::STRCONCAT) {
Init *L = BO->getLHS()->convertInitializerTo(this);
Init *R = BO->getRHS()->convertInitializerTo(this);
if (L == 0 || R == 0) return 0;
if (L != BO->getLHS() || R != BO->getRHS())
return new BinOpInit(BinOpInit::STRCONCAT, L, R);
return BO;
}
return 0;
}
Init *StringRecTy::convertValue(TypedInit *TI) {
if (dynamic_cast<StringRecTy*>(TI->getType()))
return TI; // Accept variable if already of the right type!
@ -299,21 +313,6 @@ Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) {
return this;
}
Init *IntInit::getBinaryOp(BinaryOp Op, Init *RHS) {
IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
if (RHSi == 0) return 0;
int NewValue;
switch (Op) {
default: assert(0 && "Unknown binop");
case SHL: NewValue = Value << RHSi->getValue(); break;
case SRA: NewValue = Value >> RHSi->getValue(); break;
case SRL: NewValue = (unsigned)Value >> (unsigned)RHSi->getValue(); break;
}
return new IntInit(NewValue);
}
Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
BitsInit *BI = new BitsInit(Bits.size());
@ -368,6 +367,61 @@ void ListInit::print(std::ostream &OS) const {
OS << "]";
}
Init *BinOpInit::Fold() {
switch (getOpcode()) {
default: assert(0 && "Unknown binop");
case STRCONCAT: {
StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
if (LHSs && RHSs)
return new StringInit(LHSs->getValue() + RHSs->getValue());
break;
}
case SHL:
case SRA:
case SRL: {
IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
if (LHSi && RHSi) {
int LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
int Result;
switch (getOpcode()) {
default: assert(0 && "Bad opcode!");
case SHL: Result = LHSv << RHSv; break;
case SRA: Result = LHSv >> RHSv; break;
case SRL: Result = (unsigned)LHSv >> (unsigned)RHSv; break;
}
return new IntInit(Result);
}
break;
}
}
return this;
}
Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
Init *lhs = LHS->resolveReferences(R, RV);
Init *rhs = RHS->resolveReferences(R, RV);
if (LHS != lhs || RHS != rhs)
return (new BinOpInit(getOpcode(), lhs, rhs))->Fold();
return Fold();
}
void BinOpInit::print(std::ostream &OS) const {
switch (Opc) {
case SHL: OS << "!shl"; break;
case SRA: OS << "!sra"; break;
case SRL: OS << "!srl"; break;
case STRCONCAT: OS << "!strconcat"; break;
}
OS << "(";
LHS->print(OS);
OS << ", ";
RHS->print(OS);
OS << ")";
}
Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
if (T == 0) return 0; // Cannot subscript a non-bits variable...

View File

@ -42,6 +42,7 @@ class IntInit;
class StringInit;
class CodeInit;
class ListInit;
class BinOpInit;
class DefInit;
class DagInit;
class TypedInit;
@ -75,6 +76,7 @@ public: // These methods should only be called from subclasses of Init
virtual Init *convertValue( IntInit *II) { return 0; }
virtual Init *convertValue(StringInit *SI) { return 0; }
virtual Init *convertValue( ListInit *LI) { return 0; }
virtual Init *convertValue( BinOpInit *UI) { return 0; }
virtual Init *convertValue( CodeInit *CI) { return 0; }
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( DefInit *DI) { return 0; }
@ -231,6 +233,7 @@ public:
virtual Init *convertValue( IntInit *II) { return 0; }
virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
virtual Init *convertValue( ListInit *LI) { return 0; }
virtual Init *convertValue( BinOpInit *BO);
virtual Init *convertValue( CodeInit *CI) { return 0; }
virtual Init *convertValue(VarBitInit *VB) { return 0; }
virtual Init *convertValue( DefInit *DI) { return 0; }
@ -465,11 +468,6 @@ struct Init {
return 0;
}
enum BinaryOp { SHL, SRA, SRL };
virtual Init *getBinaryOp(BinaryOp Op, Init *RHS) {
return 0;
}
/// resolveReferences - This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed.
/// If a value is set for the variable later, this method will be called on
@ -570,8 +568,6 @@ public:
}
virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
virtual Init *getBinaryOp(BinaryOp Op, Init *RHS);
virtual void print(std::ostream &OS) const { OS << Value; }
};
@ -639,6 +635,36 @@ public:
virtual void print(std::ostream &OS) const;
};
/// BinOpInit - !op (X, Y) - Combine two inits.
///
class BinOpInit : public Init {
public:
enum BinaryOp { SHL, SRA, SRL, STRCONCAT };
private:
BinaryOp Opc;
Init *LHS, *RHS;
public:
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs) : Opc(opc), LHS(lhs), RHS(rhs) {
}
BinaryOp getOpcode() const { return Opc; }
Init *getLHS() const { return LHS; }
Init *getRHS() const { return RHS; }
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold();
virtual Init *convertInitializerTo(RecTy *Ty) {
return Ty->convertValue(this);
}
virtual Init *resolveReferences(Record &R, const RecordVal *RV);
virtual void print(std::ostream &OS) const;
};
/// TypedInit - This is the common super-class of types that have a specific,
/// explicit, type.