#include "llvm/Module.h"
#include "llvm/iTerminators.h"
#include "llvm/iMemory.h"
+#include "llvm/iOperators.h"
#include "llvm/iPHINode.h"
#include "Support/STLExtras.h"
#include "Support/DepthFirstIterator.h"
#define YYERROR_VERBOSE 1
+// HACK ALERT: This variable is used to implement the automatic conversion of
+// load/store instructions with indexes into a load/store + getelementptr pair
+// of instructions. When this compatiblity "Feature" is removed, this should be
+// too.
+//
+static BasicBlock *CurBB;
+
+
// This contains info used when building the body of a function. It is
// destroyed when the function is completed.
//
// Check to make sure that "Ty" is an integral type, and that our
// value will fit into the specified type...
case ValID::ConstSIntVal: // Is it a constant pool reference??
- if (Ty == Type::BoolTy) { // Special handling for boolean data
- return ConstantBool::get(D.ConstPool64 != 0);
- } else {
- if (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64))
- ThrowException("Signed integral constant '" +
- itostr(D.ConstPool64) + "' is invalid for type '" +
- Ty->getDescription() + "'!");
- return ConstantSInt::get(Ty, D.ConstPool64);
- }
+ if (!ConstantSInt::isValueValidForType(Ty, D.ConstPool64))
+ ThrowException("Signed integral constant '" +
+ itostr(D.ConstPool64) + "' is invalid for type '" +
+ Ty->getDescription() + "'!");
+ return ConstantSInt::get(Ty, D.ConstPool64);
case ValID::ConstUIntVal: // Is it an unsigned const pool reference?
if (!ConstantUInt::isValueValidForType(Ty, D.UConstPool64)) {
ThrowException("Cannot create a a non pointer null!");
return ConstantPointerNull::get(cast<PointerType>(Ty));
+ case ValID::ConstantVal: // Fully resolved constant?
+ if (D.ConstantValue->getType() != Ty)
+ ThrowException("Constant expression type different from required type!");
+ return D.ConstantValue;
+
default:
assert(0 && "Unhandled case!");
return 0;
%token IMPLEMENTATION TRUE FALSE BEGINTOK ENDTOK DECLARE GLOBAL CONSTANT UNINIT
-%token TO EXCEPT DOTDOTDOT STRING NULL_TOK CONST INTERNAL OPAQUE NOT
+%token TO EXCEPT DOTDOTDOT NULL_TOK CONST INTERNAL OPAQUE NOT
// Basic Block Terminating Operators
%token <TermOpVal> RET BR SWITCH
// Binary Operators
%type <BinaryOpVal> BinaryOps // all the binary operators
+%type <BinaryOpVal> ArithmeticOps LogicalOps SetCondOps // Binops Subcatagories
%token <BinaryOpVal> ADD SUB MUL DIV REM AND OR XOR
%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comarators
// Operations that are notably excluded from this list include:
// RET, BR, & SWITCH because they end basic blocks and are treated specially.
//
-BinaryOps : ADD | SUB | MUL | DIV | REM | AND | OR | XOR;
-BinaryOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
+ArithmeticOps: ADD | SUB | MUL | DIV | REM;
+LogicalOps : AND | OR | XOR;
+SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
+BinaryOps : ArithmeticOps | LogicalOps | SetCondOps;
+
ShiftOps : SHL | SHR;
// These are some types that allow classification if we only want a particular
| PrimType {
$$ = new PATypeHolder($1);
};
-UpRTypes : ValueRef { // Named types are also simple types...
+UpRTypes : SymbolicValueRef { // Named types are also simple types...
$$ = new PATypeHolder(getTypeVal($1));
};
};
// ConstVal - The various declarations that go into the constant pool. This
-// includes all forward declarations of types, constants, and functions.
+// production is used ONLY to represent constants that show up AFTER a 'const',
+// 'constant' or 'global' token at global scope. Constants that can be inlined
+// into other expressions (such as integers and constexprs) are handled by the
+// ResolvedVal, ValueRef and ConstValueRef productions.
//
ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
const ArrayType *ATy = dyn_cast<const ArrayType>($1->get());
$$ = ConstantPointerRef::get(GV);
delete $1; // Free the type handle
}
- | ConstExpr {
- $$ = $1;
+ | Types ConstExpr {
+ if ($1->get() != $2->getType())
+ ThrowException("Mismatched types for constant expression!");
+ $$ = $2;
+ delete $1;
};
ConstVal : SIntType EINT64VAL { // integral constants
};
-ConstExpr: Types CAST ConstVal {
- $$ = ConstantExpr::getCast($3, $1->get());
- delete $1;
+ConstExpr: CAST '(' ConstVal TO Types ')' {
+ $$ = ConstantExpr::getCast($3, $5->get());
+ delete $5;
}
- | Types GETELEMENTPTR '(' ConstVal IndexList ')' {
- if (!isa<PointerType>($4->getType()))
+ | GETELEMENTPTR '(' ConstVal IndexList ')' {
+ if (!isa<PointerType>($3->getType()))
ThrowException("GetElementPtr requires a pointer operand!");
const Type *IdxTy =
- GetElementPtrInst::getIndexedType($4->getType(), *$5, true);
+ GetElementPtrInst::getIndexedType($3->getType(), *$4, true);
if (!IdxTy)
ThrowException("Index list invalid for constant getelementptr!");
- if (PointerType::get(IdxTy) != $1->get())
- ThrowException("Declared type of constant getelementptr is incorrect!");
vector<Constant*> IdxVec;
- for (unsigned i = 0, e = $5->size(); i != e; ++i)
- if (Constant *C = dyn_cast<Constant>((*$5)[i]))
+ for (unsigned i = 0, e = $4->size(); i != e; ++i)
+ if (Constant *C = dyn_cast<Constant>((*$4)[i]))
IdxVec.push_back(C);
else
ThrowException("Indices to constant getelementptr must be constants!");
- delete $5;
+ delete $4;
- $$ = ConstantExpr::getGetElementPtr($4, IdxVec);
- delete $1;
+ $$ = ConstantExpr::getGetElementPtr($3, IdxVec);
}
- | Types BinaryOps ConstVal ',' ConstVal {
+ | BinaryOps '(' ConstVal ',' ConstVal ')' {
if ($3->getType() != $5->getType())
ThrowException("Binary operator types must match!");
- if ($1->get() != $3->getType())
- ThrowException("Return type of binary constant must match arguments!");
- $$ = ConstantExpr::get($2, $3, $5);
- delete $1;
+ $$ = ConstantExpr::get($1, $3, $5);
}
- | Types ShiftOps ConstVal ',' ConstVal {
- if ($1->get() != $3->getType())
- ThrowException("Return type of shift constant must match argument!");
+ | ShiftOps '(' ConstVal ',' ConstVal ')' {
if ($5->getType() != Type::UByteTy)
ThrowException("Shift count for shift constant must be unsigned byte!");
-
- $$ = ConstantExpr::get($2, $3, $5);
- delete $1;
+ $$ = ConstantExpr::get($1, $3, $5);
};
$$ = ValID::create($1);
}
| TRUE {
- $$ = ValID::create((int64_t)1);
+ $$ = ValID::create(ConstantBool::True);
}
| FALSE {
- $$ = ValID::create((int64_t)0);
+ $$ = ValID::create(ConstantBool::False);
}
| NULL_TOK {
$$ = ValID::createNull();
}
- ;
+ | ConstExpr {
+ $$ = ValID::create($1);
+ };
// SymbolicValueRef - Reference to one of two ways of symbolically refering to
// another value.
// pool references (for things like: 'ret [2 x int] [ int 12, int 42]')
ResolvedVal : Types ValueRef {
$$ = getVal(*$1, $2); delete $1;
- }
- | ConstExpr {
- $$ = $1;
};
BasicBlockList : BasicBlockList BasicBlock {
$$ = $1;
}
| /* empty */ {
- $$ = new BasicBlock();
+ $$ = CurBB = new BasicBlock();
};
BBTerminatorInst : RET ResolvedVal { // Return with a result...
// ValueRefListE - Just like ValueRefList, except that it may also be empty!
ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
-InstVal : BinaryOps Types ValueRef ',' ValueRef {
+InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
+ if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint())
+ ThrowException("Arithmetic operator requires integer or FP operands!");
+ $$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
+ if ($$ == 0)
+ ThrowException("binary operator returned null!");
+ delete $2;
+ }
+ | LogicalOps Types ValueRef ',' ValueRef {
+ if (!(*$2)->isIntegral())
+ ThrowException("Logical operator requires integral operands!");
$$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
if ($$ == 0)
ThrowException("binary operator returned null!");
delete $2;
}
+ | SetCondOps Types ValueRef ',' ValueRef {
+ $$ = new SetCondInst($1, getVal(*$2, $3), getVal(*$2, $5));
+ if ($$ == 0)
+ ThrowException("binary operator returned null!");
+ delete $2;
+ }
| NOT ResolvedVal {
std::cerr << "WARNING: Use of eliminated 'not' instruction:"
<< " Replacing with 'xor'.\n";
if (!isa<PointerType>($2->get()))
ThrowException("Can't load from nonpointer type: " +
(*$2)->getDescription());
- if (LoadInst::getIndexedType(*$2, *$4) == 0)
+ if (GetElementPtrInst::getIndexedType(*$2, *$4) == 0)
ThrowException("Invalid indices for load instruction!");
- $$ = new LoadInst(getVal(*$2, $3), *$4);
+ Value *Src = getVal(*$2, $3);
+ if (!$4->empty()) {
+ std::cerr << "WARNING: Use of index load instruction:"
+ << " replacing with getelementptr/load pair.\n";
+ // Create a getelementptr hack instruction to do the right thing for
+ // compatibility.
+ //
+ Instruction *I = new GetElementPtrInst(Src, *$4);
+ CurBB->getInstList().push_back(I);
+ Src = I;
+ }
+
+ $$ = new LoadInst(Src);
delete $4; // Free the vector...
delete $2;
}
if (!isa<PointerType>($4->get()))
ThrowException("Can't store to a nonpointer type: " +
(*$4)->getDescription());
- const Type *ElTy = StoreInst::getIndexedType(*$4, *$6);
+ const Type *ElTy = GetElementPtrInst::getIndexedType(*$4, *$6);
if (ElTy == 0)
ThrowException("Can't store into that field list!");
if (ElTy != $2->getType())
ThrowException("Can't store '" + $2->getType()->getDescription() +
"' into space of type '" + ElTy->getDescription() + "'!");
- $$ = new StoreInst($2, getVal(*$4, $5), *$6);
+
+ Value *Ptr = getVal(*$4, $5);
+ if (!$6->empty()) {
+ std::cerr << "WARNING: Use of index store instruction:"
+ << " replacing with getelementptr/store pair.\n";
+ // Create a getelementptr hack instruction to do the right thing for
+ // compatibility.
+ //
+ Instruction *I = new GetElementPtrInst(Ptr, *$6);
+ CurBB->getInstList().push_back(I);
+ Ptr = I;
+ }
+
+ $$ = new StoreInst($2, Ptr);
delete $4; delete $6;
}
| GETELEMENTPTR Types ValueRef IndexList {