mirror of
https://github.com/RPCSX/llvm.git
synced 2025-03-02 01:47:06 +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
utils/TableGen
@ -202,6 +202,7 @@ in { return IN; }
|
|||||||
!sra { return SRATOK; }
|
!sra { return SRATOK; }
|
||||||
!srl { return SRLTOK; }
|
!srl { return SRLTOK; }
|
||||||
!shl { return SHLTOK; }
|
!shl { return SHLTOK; }
|
||||||
|
!strconcat { return STRCONCATTOK; }
|
||||||
|
|
||||||
|
|
||||||
{Identifier} { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
|
{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 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 <IntVal> INTVAL
|
||||||
%token <StrVal> ID VARNAME STRVAL CODEFRAGMENT
|
%token <StrVal> ID VARNAME STRVAL CODEFRAGMENT
|
||||||
|
|
||||||
@ -352,23 +352,13 @@ Value : IDValue {
|
|||||||
}
|
}
|
||||||
delete $3;
|
delete $3;
|
||||||
} | SHLTOK '(' Value ',' Value ')' {
|
} | SHLTOK '(' Value ',' Value ')' {
|
||||||
$$ = $3->getBinaryOp(Init::SHL, $5);
|
$$ = (new BinOpInit(BinOpInit::SHL, $3, $5))->Fold();
|
||||||
if ($$ == 0) {
|
|
||||||
err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} | SRATOK '(' Value ',' Value ')' {
|
} | SRATOK '(' Value ',' Value ')' {
|
||||||
$$ = $3->getBinaryOp(Init::SRA, $5);
|
$$ = (new BinOpInit(BinOpInit::SRA, $3, $5))->Fold();
|
||||||
if ($$ == 0) {
|
|
||||||
err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} | SRLTOK '(' Value ',' Value ')' {
|
} | SRLTOK '(' Value ',' Value ')' {
|
||||||
$$ = $3->getBinaryOp(Init::SRL, $5);
|
$$ = (new BinOpInit(BinOpInit::SRL, $3, $5))->Fold();
|
||||||
if ($$ == 0) {
|
} | STRCONCATTOK '(' Value ',' Value ')' {
|
||||||
err() << "Cannot shift values '" << *$3 << "' and '" << *$5 << "'!\n";
|
$$ = (new BinOpInit(BinOpInit::STRCONCAT, $3, $5))->Fold();
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OptVarName : /* empty */ {
|
OptVarName : /* empty */ {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
|
// Implement the tablegen record classes.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
@ -125,6 +126,19 @@ Init *IntRecTy::convertValue(TypedInit *TI) {
|
|||||||
return 0;
|
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) {
|
Init *StringRecTy::convertValue(TypedInit *TI) {
|
||||||
if (dynamic_cast<StringRecTy*>(TI->getType()))
|
if (dynamic_cast<StringRecTy*>(TI->getType()))
|
||||||
return TI; // Accept variable if already of the right type!
|
return TI; // Accept variable if already of the right type!
|
||||||
@ -299,21 +313,6 @@ Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) {
|
|||||||
return this;
|
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) {
|
Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
|
||||||
BitsInit *BI = new BitsInit(Bits.size());
|
BitsInit *BI = new BitsInit(Bits.size());
|
||||||
|
|
||||||
@ -368,6 +367,61 @@ void ListInit::print(std::ostream &OS) const {
|
|||||||
OS << "]";
|
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) {
|
Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
|
||||||
BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
|
BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
|
||||||
if (T == 0) return 0; // Cannot subscript a non-bits variable...
|
if (T == 0) return 0; // Cannot subscript a non-bits variable...
|
||||||
|
@ -42,6 +42,7 @@ class IntInit;
|
|||||||
class StringInit;
|
class StringInit;
|
||||||
class CodeInit;
|
class CodeInit;
|
||||||
class ListInit;
|
class ListInit;
|
||||||
|
class BinOpInit;
|
||||||
class DefInit;
|
class DefInit;
|
||||||
class DagInit;
|
class DagInit;
|
||||||
class TypedInit;
|
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( IntInit *II) { return 0; }
|
||||||
virtual Init *convertValue(StringInit *SI) { return 0; }
|
virtual Init *convertValue(StringInit *SI) { return 0; }
|
||||||
virtual Init *convertValue( ListInit *LI) { 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( CodeInit *CI) { return 0; }
|
||||||
virtual Init *convertValue(VarBitInit *VB) { return 0; }
|
virtual Init *convertValue(VarBitInit *VB) { return 0; }
|
||||||
virtual Init *convertValue( DefInit *DI) { return 0; }
|
virtual Init *convertValue( DefInit *DI) { return 0; }
|
||||||
@ -231,6 +233,7 @@ public:
|
|||||||
virtual Init *convertValue( IntInit *II) { return 0; }
|
virtual Init *convertValue( IntInit *II) { return 0; }
|
||||||
virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
|
virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
|
||||||
virtual Init *convertValue( ListInit *LI) { return 0; }
|
virtual Init *convertValue( ListInit *LI) { return 0; }
|
||||||
|
virtual Init *convertValue( BinOpInit *BO);
|
||||||
virtual Init *convertValue( CodeInit *CI) { return 0; }
|
virtual Init *convertValue( CodeInit *CI) { return 0; }
|
||||||
virtual Init *convertValue(VarBitInit *VB) { return 0; }
|
virtual Init *convertValue(VarBitInit *VB) { return 0; }
|
||||||
virtual Init *convertValue( DefInit *DI) { return 0; }
|
virtual Init *convertValue( DefInit *DI) { return 0; }
|
||||||
@ -465,11 +468,6 @@ struct Init {
|
|||||||
return 0;
|
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
|
/// resolveReferences - This method is used by classes that refer to other
|
||||||
/// variables which may not be defined at the time they expression is formed.
|
/// 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
|
/// 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 *convertInitializerBitRange(const std::vector<unsigned> &Bits);
|
||||||
|
|
||||||
virtual Init *getBinaryOp(BinaryOp Op, Init *RHS);
|
|
||||||
|
|
||||||
virtual void print(std::ostream &OS) const { OS << Value; }
|
virtual void print(std::ostream &OS) const { OS << Value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -639,6 +635,36 @@ public:
|
|||||||
virtual void print(std::ostream &OS) const;
|
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,
|
/// TypedInit - This is the common super-class of types that have a specific,
|
||||||
/// explicit, type.
|
/// explicit, type.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user