mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-31 09:22:31 +00:00
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:
parent
fd2ae97ac3
commit
711e5d96aa
@ -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);
|
||||
|
@ -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 */ {
|
||||
|
@ -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...
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user