diff options
Diffstat (limited to 'lib/AsmParser/llvmAsmParser.y.cvs')
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y.cvs | 83 |
1 files changed, 64 insertions, 19 deletions
diff --git a/lib/AsmParser/llvmAsmParser.y.cvs b/lib/AsmParser/llvmAsmParser.y.cvs index 425d2abb89..684b643bba 100644 --- a/lib/AsmParser/llvmAsmParser.y.cvs +++ b/lib/AsmParser/llvmAsmParser.y.cvs @@ -813,6 +813,43 @@ static PATypeHolder HandleUpRefs(const Type *ty) { return Ty; } +/// This function is used to obtain the correct opcode for an instruction when +/// an obsolete opcode is encountered. The OI parameter (OpcodeInfo) has both +/// an opcode and an "obsolete" flag. These are generated by the lexer and +/// the "obsolete" member will be true when the lexer encounters the token for +/// an obsolete opcode. For example, "div" was replaced by [usf]div but we need +/// to maintain backwards compatibility for asm files that still have the "div" +/// instruction. This function handles converting div -> [usf]div appropriately. +/// @brief Convert obsolete opcodes to new values +static void +sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const PATypeHolder& PATy) +{ + // If its not obsolete, don't do anything + if (!OI.obsolete) + return; + + // If its a packed type we want to use the element type + const Type* Ty = PATy; + if (const PackedType* PTy = dyn_cast<PackedType>(Ty)) + Ty = PTy->getElementType(); + + // Depending on the opcode .. + switch (OI.opcode) { + default: + GenerateError("Invalid Obsolete OpCode"); + break; + case Instruction::UDiv: + // Handle cases where the opcode needs to change + if (Ty->isFloatingPoint()) + OI.opcode = Instruction::FDiv; + else if (Ty->isSigned()) + OI.opcode = Instruction::SDiv; + break; + } + // Its not obsolete any more, we fixed it. + OI.obsolete = false; +} + // common code from the two 'RunVMAsmParser' functions static Module* RunParser(Module * M) { @@ -1002,13 +1039,13 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { bool BoolVal; char *StrVal; // This memory is strdup'd! - llvm::ValID ValIDVal; // strdup'd memory maybe! + llvm::ValID ValIDVal; // strdup'd memory maybe! - llvm::Instruction::BinaryOps BinaryOpVal; - llvm::Instruction::TermOps TermOpVal; - llvm::Instruction::MemoryOps MemOpVal; - llvm::Instruction::OtherOps OtherOpVal; - llvm::Module::Endianness Endianness; + BinaryOpInfo BinaryOpVal; + TermOpInfo TermOpVal; + MemOpInfo MemOpVal; + OtherOpInfo OtherOpVal; + llvm::Module::Endianness Endianness; } %type <ModuleVal> Module FunctionList @@ -1076,8 +1113,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { // 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 +%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV REM AND OR XOR +%token <BinaryOpVal> SETLE SETGE SETLT SETGT SETEQ SETNE // Binary Comparators // Memory Instructions %token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR @@ -1114,7 +1151,7 @@ EINT64VAL : EUINT64VAL { // Operations that are notably excluded from this list include: // RET, BR, & SWITCH because they end basic blocks and are treated specially. // -ArithmeticOps: ADD | SUB | MUL | DIV | REM; +ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | REM ; LogicalOps : AND | OR | XOR; SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE; @@ -1642,12 +1679,17 @@ ConstExpr: CAST '(' ConstVal TO Types ')' { | ArithmeticOps '(' ConstVal ',' ConstVal ')' { if ($3->getType() != $5->getType()) GEN_ERROR("Binary operator types must match!"); + // First, make sure we're dealing with the right opcode by upgrading from + // obsolete versions. + sanitizeOpCode($1,$3->getType()); + CHECK_FOR_ERROR; + // HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs. // To retain backward compatibility with these early compilers, we emit a // cast to the appropriate integer type automatically if we are in the // broken case. See PR424 for more information. if (!isa<PointerType>($3->getType())) { - $$ = ConstantExpr::get($1, $3, $5); + $$ = ConstantExpr::get($1.opcode, $3, $5); } else { const Type *IntPtrTy = 0; switch (CurModule.CurrentModule->getPointerSize()) { @@ -1655,7 +1697,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' { case Module::Pointer64: IntPtrTy = Type::LongTy; break; default: GEN_ERROR("invalid pointer binary constant expr!"); } - $$ = ConstantExpr::get($1, ConstantExpr::getCast($3, IntPtrTy), + $$ = ConstantExpr::get($1.opcode, ConstantExpr::getCast($3, IntPtrTy), ConstantExpr::getCast($5, IntPtrTy)); $$ = ConstantExpr::getCast($$, $3->getType()); } @@ -1669,13 +1711,13 @@ ConstExpr: CAST '(' ConstVal TO Types ')' { !cast<PackedType>($3->getType())->getElementType()->isIntegral()) GEN_ERROR("Logical operator requires integral operands!"); } - $$ = ConstantExpr::get($1, $3, $5); + $$ = ConstantExpr::get($1.opcode, $3, $5); CHECK_FOR_ERROR } | SetCondOps '(' ConstVal ',' ConstVal ')' { if ($3->getType() != $5->getType()) GEN_ERROR("setcc operand types must match!"); - $$ = ConstantExpr::get($1, $3, $5); + $$ = ConstantExpr::get($1.opcode, $3, $5); CHECK_FOR_ERROR } | ShiftOps '(' ConstVal ',' ConstVal ')' { @@ -1683,7 +1725,7 @@ ConstExpr: CAST '(' ConstVal TO Types ')' { GEN_ERROR("Shift count for shift constant must be unsigned byte!"); if (!$3->getType()->isInteger()) GEN_ERROR("Shift constant expression requires integer operand!"); - $$ = ConstantExpr::get($1, $3, $5); + $$ = ConstantExpr::get($1.opcode, $3, $5); CHECK_FOR_ERROR } | EXTRACTELEMENT '(' ConstVal ',' ConstVal ')' { @@ -2423,13 +2465,16 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { !isa<PackedType>((*$2).get())) GEN_ERROR( "Arithmetic operator requires integer, FP, or packed operands!"); - if (isa<PackedType>((*$2).get()) && $1 == Instruction::Rem) + if (isa<PackedType>((*$2).get()) && $1.opcode == Instruction::Rem) GEN_ERROR("Rem not supported on packed types!"); + // Upgrade the opcode from obsolete versions before we do anything with it. + sanitizeOpCode($1,*$2); + CHECK_FOR_ERROR; Value* val1 = getVal(*$2, $3); CHECK_FOR_ERROR Value* val2 = getVal(*$2, $5); CHECK_FOR_ERROR - $$ = BinaryOperator::create($1, val1, val2); + $$ = BinaryOperator::create($1.opcode, val1, val2); if ($$ == 0) GEN_ERROR("binary operator returned null!"); delete $2; @@ -2444,7 +2489,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { CHECK_FOR_ERROR Value* tmpVal2 = getVal(*$2, $5); CHECK_FOR_ERROR - $$ = BinaryOperator::create($1, tmpVal1, tmpVal2); + $$ = BinaryOperator::create($1.opcode, tmpVal1, tmpVal2); if ($$ == 0) GEN_ERROR("binary operator returned null!"); delete $2; @@ -2458,7 +2503,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { CHECK_FOR_ERROR Value* tmpVal2 = getVal(*$2, $5); CHECK_FOR_ERROR - $$ = new SetCondInst($1, tmpVal1, tmpVal2); + $$ = new SetCondInst($1.opcode, tmpVal1, tmpVal2); if ($$ == 0) GEN_ERROR("binary operator returned null!"); delete $2; @@ -2481,7 +2526,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { GEN_ERROR("Shift amount must be ubyte!"); if (!$2->getType()->isInteger()) GEN_ERROR("Shift constant expression requires integer operand!"); - $$ = new ShiftInst($1, $2, $4); + $$ = new ShiftInst($1.opcode, $2, $4); CHECK_FOR_ERROR } | CAST ResolvedVal TO Types { |