فهرست منبع

Make structs and arrays first-class types, and add assembly
and bitcode support for the extractvalue and insertvalue
instructions and constant expressions.

Note that this does not yet include CodeGen support.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51468 91177308-0d34-0410-b5e6-96231b3b80d8

Dan Gohman 17 سال پیش
والد
کامیت
e4977cf750

+ 6 - 2
include/llvm/Bitcode/LLVMBitCodes.h

@@ -125,7 +125,9 @@ namespace bitc {
     CST_CODE_CE_INSERTELT  = 15,  // CE_INSERTELT:  [opval, opval, opval]
     CST_CODE_CE_SHUFFLEVEC = 16,  // CE_SHUFFLEVEC: [opval, opval, opval]
     CST_CODE_CE_CMP        = 17,  // CE_CMP:        [opty, opval, opval, pred]
-    CST_CODE_INLINEASM     = 18   // INLINEASM:     [sideeffect,asmstr,conststr]
+    CST_CODE_INLINEASM     = 18,  // INLINEASM:     [sideeffect,asmstr,conststr]
+    CST_CODE_CE_EXTRACTVAL = 19,  // CE_EXTRACTVAL: [n x operands]
+    CST_CODE_CE_INSERTVAL  = 20   // CE_INSERTVAL:  [n x operands]
   };
   
   /// CastOpcodes - These are values used in the bitcode files to encode which
@@ -202,7 +204,9 @@ namespace bitc {
     // this is so information only available in the pointer type (e.g. address
     // spaces) is retained.
     FUNC_CODE_INST_STORE2      = 24, // STORE:      [ptrty,ptr,val, align, vol]
-    FUNC_CODE_INST_GETRESULT   = 25  // GETRESULT:  [ty, opval, n]
+    FUNC_CODE_INST_GETRESULT   = 25, // GETRESULT:  [ty, opval, n]
+    FUNC_CODE_INST_EXTRACTVAL  = 26, // EXTRACTVAL: [n x operands]
+    FUNC_CODE_INST_INSERTVAL   = 27  // INSERTVAL:  [n x operands]
   };
 } // End bitc namespace
 } // End llvm namespace

+ 2 - 2
include/llvm/Type.h

@@ -216,8 +216,8 @@ public:
   /// is a valid type for a Value.
   ///
   inline bool isFirstClassType() const {
-    // Coming soon: first-class struct and array types...
-    return isSingleValueType();
+    return isSingleValueType() ||
+           ID == StructTyID || ID == ArrayTyID;
   }
 
   /// isSingleValueType - Return true if the type is a valid type for a

+ 2 - 0
lib/AsmParser/LLLexer.cpp

@@ -605,6 +605,8 @@ int LLLexer::LexIdentifier() {
   INSTKEYWORD("insertelement", OtherOpVal, InsertElement, INSERTELEMENT);
   INSTKEYWORD("shufflevector", OtherOpVal, ShuffleVector, SHUFFLEVECTOR);
   INSTKEYWORD("getresult", OtherOpVal, GetResult, GETRESULT);
+  INSTKEYWORD("extractvalue", OtherOpVal, ExtractValue, EXTRACTVALUE);
+  INSTKEYWORD("insertvalue", OtherOpVal, InsertValue, INSERTVALUE);
 #undef INSTKEYWORD
 
   // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 792 - 756
lib/AsmParser/llvmAsmParser.cpp.cvs


+ 36 - 32
lib/AsmParser/llvmAsmParser.h.cvs

@@ -175,21 +175,23 @@
      INSERTELEMENT = 391,
      SHUFFLEVECTOR = 392,
      GETRESULT = 393,
-     SIGNEXT = 394,
-     ZEROEXT = 395,
-     NORETURN = 396,
-     INREG = 397,
-     SRET = 398,
-     NOUNWIND = 399,
-     NOALIAS = 400,
-     BYVAL = 401,
-     NEST = 402,
-     READNONE = 403,
-     READONLY = 404,
-     GC = 405,
-     DEFAULT = 406,
-     HIDDEN = 407,
-     PROTECTED = 408
+     EXTRACTVALUE = 394,
+     INSERTVALUE = 395,
+     SIGNEXT = 396,
+     ZEROEXT = 397,
+     NORETURN = 398,
+     INREG = 399,
+     SRET = 400,
+     NOUNWIND = 401,
+     NOALIAS = 402,
+     BYVAL = 403,
+     NEST = 404,
+     READNONE = 405,
+     READONLY = 406,
+     GC = 407,
+     DEFAULT = 408,
+     HIDDEN = 409,
+     PROTECTED = 410
    };
 #endif
 /* Tokens.  */
@@ -329,28 +331,30 @@
 #define INSERTELEMENT 391
 #define SHUFFLEVECTOR 392
 #define GETRESULT 393
-#define SIGNEXT 394
-#define ZEROEXT 395
-#define NORETURN 396
-#define INREG 397
-#define SRET 398
-#define NOUNWIND 399
-#define NOALIAS 400
-#define BYVAL 401
-#define NEST 402
-#define READNONE 403
-#define READONLY 404
-#define GC 405
-#define DEFAULT 406
-#define HIDDEN 407
-#define PROTECTED 408
+#define EXTRACTVALUE 394
+#define INSERTVALUE 395
+#define SIGNEXT 396
+#define ZEROEXT 397
+#define NORETURN 398
+#define INREG 399
+#define SRET 400
+#define NOUNWIND 401
+#define NOALIAS 402
+#define BYVAL 403
+#define NEST 404
+#define READNONE 405
+#define READONLY 406
+#define GC 407
+#define DEFAULT 408
+#define HIDDEN 409
+#define PROTECTED 410
 
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 949 "/Volumes/LLVM/llvm/lib/AsmParser/llvmAsmParser.y"
+#line 949 "/Users/gohman/LLVM/llvm/lib/AsmParser/llvmAsmParser.y"
 {
   llvm::Module                           *ModuleVal;
   llvm::Function                         *FunctionVal;
@@ -398,7 +402,7 @@ typedef union YYSTYPE
   llvm::FCmpInst::Predicate         FPredicate;
 }
 /* Line 1529 of yacc.c.  */
-#line 402 "llvmAsmParser.tab.h"
+#line 406 "llvmAsmParser.tab.h"
 	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1

+ 77 - 2
lib/AsmParser/llvmAsmParser.y

@@ -475,7 +475,7 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
   if (TriggerError) return 0;
 
   if (!Ty->isFirstClassType() && !isa<OpaqueType>(Ty)) {
-    GenerateError("Invalid use of a composite type");
+    GenerateError("Invalid use of a non-first-class type");
     return 0;
   }
 
@@ -1093,6 +1093,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
 %token <OtherOpVal> PHI_TOK SELECT VAARG
 %token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
 %token <OtherOpVal> GETRESULT
+%token <OtherOpVal> EXTRACTVALUE INSERTVALUE
 
 // Function Attributes
 %token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
@@ -1966,6 +1967,48 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
       GEN_ERROR("Invalid shufflevector operands");
     $$ = ConstantExpr::getShuffleVector($3, $5, $7);
     CHECK_FOR_ERROR
+  }
+  | EXTRACTVALUE '(' ConstVal IndexList ')' {
+    if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
+      GEN_ERROR("ExtractValue requires an aggregate operand");
+
+    const Type *IdxTy =
+      ExtractValueInst::getIndexedType($3->getType(), $4->begin(), $4->end());
+    if (!IdxTy)
+      GEN_ERROR("Index list invalid for constant extractvalue");
+
+    SmallVector<Constant*, 8> IdxVec;
+    for (unsigned i = 0, e = $4->size(); i != e; ++i)
+      if (Constant *C = dyn_cast<Constant>((*$4)[i]))
+        IdxVec.push_back(C);
+      else
+        GEN_ERROR("Indices to constant extractvalue must be constants");
+
+    delete $4;
+
+    $$ = ConstantExpr::getExtractValue($3, &IdxVec[0], IdxVec.size());
+    CHECK_FOR_ERROR
+  }
+  | INSERTVALUE '(' ConstVal ',' ConstVal IndexList ')' {
+    if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
+      GEN_ERROR("InsertValue requires an aggregate operand");
+
+    const Type *IdxTy =
+      ExtractValueInst::getIndexedType($3->getType(), $6->begin(), $6->end());
+    if (IdxTy != $5->getType())
+      GEN_ERROR("Index list invalid for constant insertvalue");
+
+    SmallVector<Constant*, 8> IdxVec;
+    for (unsigned i = 0, e = $6->size(); i != e; ++i)
+      if (Constant *C = dyn_cast<Constant>((*$6)[i]))
+        IdxVec.push_back(C);
+      else
+        GEN_ERROR("Indices to constant insertvalue must be constants");
+
+    delete $6;
+
+    $$ = ConstantExpr::getInsertValue($3, $5, &IdxVec[0], IdxVec.size());
+    CHECK_FOR_ERROR
   };
 
 
@@ -3165,7 +3208,7 @@ MemoryInst : MALLOC Types OptCAlign {
     $$ = new StoreInst($3, tmpVal, $1, $7);
     delete $5;
   }
-| GETRESULT Types ValueRef ',' EUINT64VAL  {
+  | GETRESULT Types ValueRef ',' EUINT64VAL  {
   Value *TmpVal = getVal($2->get(), $3);
   if (!GetResultInst::isValidOperands(TmpVal, $5))
       GEN_ERROR("Invalid getresult operands");
@@ -3187,6 +3230,38 @@ MemoryInst : MALLOC Types OptCAlign {
     $$ = GetElementPtrInst::Create(tmpVal, $4->begin(), $4->end());
     delete $2; 
     delete $4;
+  }
+  | EXTRACTVALUE Types ValueRef IndexList {
+    if (!UpRefs.empty())
+      GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
+    if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
+      GEN_ERROR("extractvalue insn requires an aggregate operand");
+
+    if (!ExtractValueInst::getIndexedType(*$2, $4->begin(), $4->end()))
+      GEN_ERROR("Invalid extractvalue indices for type '" +
+                     (*$2)->getDescription()+ "'");
+    Value* tmpVal = getVal(*$2, $3);
+    CHECK_FOR_ERROR
+    $$ = ExtractValueInst::Create(tmpVal, $4->begin(), $4->end());
+    delete $2; 
+    delete $4;
+  }
+  | INSERTVALUE Types ValueRef ',' Types ValueRef IndexList {
+    if (!UpRefs.empty())
+      GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
+    if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
+      GEN_ERROR("extractvalue insn requires an aggregate operand");
+
+    if (ExtractValueInst::getIndexedType(*$2, $7->begin(), $7->end()) != $5->get())
+      GEN_ERROR("Invalid insertvalue indices for type '" +
+                     (*$2)->getDescription()+ "'");
+    Value* aggVal = getVal(*$2, $3);
+    Value* tmpVal = getVal(*$5, $6);
+    CHECK_FOR_ERROR
+    $$ = InsertValueInst::Create(aggVal, tmpVal, $7->begin(), $7->end());
+    delete $2; 
+    delete $5;
+    delete $7;
   };
 
 

+ 84 - 9
lib/AsmParser/llvmAsmParser.y.cvs

@@ -475,7 +475,7 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
   if (TriggerError) return 0;
 
   if (!Ty->isFirstClassType() && !isa<OpaqueType>(Ty)) {
-    GenerateError("Invalid use of a composite type");
+    GenerateError("Invalid use of a non-first-class type");
     return 0;
   }
 
@@ -1093,6 +1093,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
 %token <OtherOpVal> PHI_TOK SELECT VAARG
 %token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
 %token <OtherOpVal> GETRESULT
+%token <OtherOpVal> EXTRACTVALUE INSERTVALUE
 
 // Function Attributes
 %token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
@@ -1966,6 +1967,48 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
       GEN_ERROR("Invalid shufflevector operands");
     $$ = ConstantExpr::getShuffleVector($3, $5, $7);
     CHECK_FOR_ERROR
+  }
+  | EXTRACTVALUE '(' ConstVal IndexList ')' {
+    if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
+      GEN_ERROR("ExtractValue requires an aggregate operand");
+
+    const Type *IdxTy =
+      ExtractValueInst::getIndexedType($3->getType(), $4->begin(), $4->end());
+    if (!IdxTy)
+      GEN_ERROR("Index list invalid for constant extractvalue");
+
+    SmallVector<Constant*, 8> IdxVec;
+    for (unsigned i = 0, e = $4->size(); i != e; ++i)
+      if (Constant *C = dyn_cast<Constant>((*$4)[i]))
+        IdxVec.push_back(C);
+      else
+        GEN_ERROR("Indices to constant extractvalue must be constants");
+
+    delete $4;
+
+    $$ = ConstantExpr::getExtractValue($3, &IdxVec[0], IdxVec.size());
+    CHECK_FOR_ERROR
+  }
+  | INSERTVALUE '(' ConstVal ',' ConstVal IndexList ')' {
+    if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
+      GEN_ERROR("InsertValue requires an aggregate operand");
+
+    const Type *IdxTy =
+      ExtractValueInst::getIndexedType($3->getType(), $6->begin(), $6->end());
+    if (IdxTy != $5->getType())
+      GEN_ERROR("Index list invalid for constant insertvalue");
+
+    SmallVector<Constant*, 8> IdxVec;
+    for (unsigned i = 0, e = $6->size(); i != e; ++i)
+      if (Constant *C = dyn_cast<Constant>((*$6)[i]))
+        IdxVec.push_back(C);
+      else
+        GEN_ERROR("Indices to constant insertvalue must be constants");
+
+    delete $6;
+
+    $$ = ConstantExpr::getInsertValue($3, $5, &IdxVec[0], IdxVec.size());
+    CHECK_FOR_ERROR
   };
 
 
@@ -2852,7 +2895,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     CHECK_FOR_ERROR
     Value* val2 = getVal(*$2, $5);
     CHECK_FOR_ERROR
-    $$ = BinaryOperator::create($1, val1, val2);
+    $$ = BinaryOperator::Create($1, val1, val2);
     if ($$ == 0)
       GEN_ERROR("binary operator returned null");
     delete $2;
@@ -2869,7 +2912,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, tmpVal1, tmpVal2);
     if ($$ == 0)
       GEN_ERROR("binary operator returned null");
     delete $2;
@@ -2883,7 +2926,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     CHECK_FOR_ERROR
     Value* tmpVal2 = getVal(*$3, $6);
     CHECK_FOR_ERROR
-    $$ = CmpInst::create($1, $2, tmpVal1, tmpVal2);
+    $$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
     if ($$ == 0)
       GEN_ERROR("icmp operator returned null");
     delete $3;
@@ -2897,7 +2940,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     CHECK_FOR_ERROR
     Value* tmpVal2 = getVal(*$3, $6);
     CHECK_FOR_ERROR
-    $$ = CmpInst::create($1, $2, tmpVal1, tmpVal2);
+    $$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
     if ($$ == 0)
       GEN_ERROR("fcmp operator returned null");
     delete $3;
@@ -2911,7 +2954,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     CHECK_FOR_ERROR
     Value* tmpVal2 = getVal(*$3, $6);
     CHECK_FOR_ERROR
-    $$ = CmpInst::create($1, $2, tmpVal1, tmpVal2);
+    $$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
     if ($$ == 0)
       GEN_ERROR("icmp operator returned null");
     delete $3;
@@ -2925,7 +2968,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     CHECK_FOR_ERROR
     Value* tmpVal2 = getVal(*$3, $6);
     CHECK_FOR_ERROR
-    $$ = CmpInst::create($1, $2, tmpVal1, tmpVal2);
+    $$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
     if ($$ == 0)
       GEN_ERROR("fcmp operator returned null");
     delete $3;
@@ -2939,7 +2982,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
       GEN_ERROR("invalid cast opcode for cast from '" +
                 Val->getType()->getDescription() + "' to '" +
                 DestTy->getDescription() + "'"); 
-    $$ = CastInst::create($1, Val, DestTy);
+    $$ = CastInst::Create($1, Val, DestTy);
     delete $4;
   }
   | SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
@@ -3165,7 +3208,7 @@ MemoryInst : MALLOC Types OptCAlign {
     $$ = new StoreInst($3, tmpVal, $1, $7);
     delete $5;
   }
-| GETRESULT Types ValueRef ',' EUINT64VAL  {
+  | GETRESULT Types ValueRef ',' EUINT64VAL  {
   Value *TmpVal = getVal($2->get(), $3);
   if (!GetResultInst::isValidOperands(TmpVal, $5))
       GEN_ERROR("Invalid getresult operands");
@@ -3187,6 +3230,38 @@ MemoryInst : MALLOC Types OptCAlign {
     $$ = GetElementPtrInst::Create(tmpVal, $4->begin(), $4->end());
     delete $2; 
     delete $4;
+  }
+  | EXTRACTVALUE Types ValueRef IndexList {
+    if (!UpRefs.empty())
+      GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
+    if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
+      GEN_ERROR("extractvalue insn requires an aggregate operand");
+
+    if (!ExtractValueInst::getIndexedType(*$2, $4->begin(), $4->end()))
+      GEN_ERROR("Invalid extractvalue indices for type '" +
+                     (*$2)->getDescription()+ "'");
+    Value* tmpVal = getVal(*$2, $3);
+    CHECK_FOR_ERROR
+    $$ = ExtractValueInst::Create(tmpVal, $4->begin(), $4->end());
+    delete $2; 
+    delete $4;
+  }
+  | INSERTVALUE Types ValueRef ',' Types ValueRef IndexList {
+    if (!UpRefs.empty())
+      GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
+    if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
+      GEN_ERROR("extractvalue insn requires an aggregate operand");
+
+    if (ExtractValueInst::getIndexedType(*$2, $7->begin(), $7->end()) != $5->get())
+      GEN_ERROR("Invalid insertvalue indices for type '" +
+                     (*$2)->getDescription()+ "'");
+    Value* aggVal = getVal(*$2, $3);
+    Value* tmpVal = getVal(*$5, $6);
+    CHECK_FOR_ERROR
+    $$ = InsertValueInst::Create(aggVal, tmpVal, $7->begin(), $7->end());
+    delete $2; 
+    delete $5;
+    delete $7;
   };
 
 

+ 64 - 0
lib/Bitcode/Reader/BitcodeReader.cpp

@@ -770,6 +770,29 @@ bool BitcodeReader::ParseConstants() {
       V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], Elts.size()-1);
       break;
     }
+    case bitc::CST_CODE_CE_EXTRACTVAL: { // CE_EXTRACTVAL: [n x operands]
+      if (Record.size() & 1) return Error("Invalid CE_EXTRACTVAL record");
+      SmallVector<Constant*, 16> Elts;
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        const Type *ElTy = getTypeByID(Record[i]);
+        if (!ElTy) return Error("Invalid CE_EXTRACTVAL record");
+        Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
+      }
+      V = ConstantExpr::getExtractValue(Elts[0], &Elts[1], Elts.size()-1);
+      break;
+    }
+    case bitc::CST_CODE_CE_INSERTVAL: { // CE_INSERTVAL: [n x operands]
+      if (Record.size() & 1) return Error("Invalid CE_INSERTVAL record");
+      SmallVector<Constant*, 16> Elts;
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        const Type *ElTy = getTypeByID(Record[i]);
+        if (!ElTy) return Error("Invalid CE_INSERTVAL record");
+        Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
+      }
+      V = ConstantExpr::getInsertValue(Elts[0], Elts[1],
+                                       &Elts[2], Elts.size()-1);
+      break;
+    }
     case bitc::CST_CODE_CE_SELECT:  // CE_SELECT: [opval#, opval#, opval#]
       if (Record.size() < 3) return Error("Invalid CE_SELECT record");
       V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0],
@@ -1301,6 +1324,47 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
       break;
     }
       
+    case bitc::FUNC_CODE_INST_EXTRACTVAL: { // EXTRACTVAL: [n x operands]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid EXTRACTVAL record");
+
+      SmallVector<Value*, 16> EXTRACTVALIdx;
+      while (OpNum != Record.size()) {
+        Value *Op;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid EXTRACTVAL record");
+        EXTRACTVALIdx.push_back(Op);
+      }
+
+      I = ExtractValueInst::Create(Agg,
+                                   EXTRACTVALIdx.begin(), EXTRACTVALIdx.end());
+      break;
+    }
+      
+    case bitc::FUNC_CODE_INST_INSERTVAL: { // INSERTVAL: [n x operands]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid INSERTVAL record");
+      Value *Val;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Val))
+        return Error("Invalid INSERTVAL record");
+
+      SmallVector<Value*, 16> INSERTVALIdx;
+      while (OpNum != Record.size()) {
+        Value *Op;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid INSERTVAL record");
+        INSERTVALIdx.push_back(Op);
+      }
+
+      I = InsertValueInst::Create(Agg, Val,
+                                  INSERTVALIdx.begin(), INSERTVALIdx.end());
+      break;
+    }
+      
     case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval]
       unsigned OpNum = 0;
       Value *TrueVal, *FalseVal, *Cond;

+ 24 - 0
lib/Bitcode/Writer/BitcodeWriter.cpp

@@ -610,6 +610,20 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
           Record.push_back(VE.getValueID(C->getOperand(i)));
         }
         break;
+      case Instruction::ExtractValue:
+        Code = bitc::CST_CODE_CE_EXTRACTVAL;
+        for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
+          Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
+          Record.push_back(VE.getValueID(C->getOperand(i)));
+        }
+        break;
+      case Instruction::InsertValue:
+        Code = bitc::CST_CODE_CE_INSERTVAL;
+        for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
+          Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
+          Record.push_back(VE.getValueID(C->getOperand(i)));
+        }
+        break;
       case Instruction::Select:
         Code = bitc::CST_CODE_CE_SELECT;
         Record.push_back(VE.getValueID(C->getOperand(0)));
@@ -718,6 +732,16 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
     for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
       PushValueAndType(I.getOperand(i), InstID, Vals, VE);
     break;
+  case Instruction::ExtractValue:
+    Code = bitc::FUNC_CODE_INST_EXTRACTVAL;
+    for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
+      PushValueAndType(I.getOperand(i), InstID, Vals, VE);
+    break;
+  case Instruction::InsertValue:
+    Code = bitc::FUNC_CODE_INST_INSERTVAL;
+    for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
+      PushValueAndType(I.getOperand(i), InstID, Vals, VE);
+    break;
   case Instruction::Select:
     Code = bitc::FUNC_CODE_INST_SELECT;
     PushValueAndType(I.getOperand(1), InstID, Vals, VE);

+ 7 - 7
lib/Bitcode/Writer/ValueEnumerator.cpp

@@ -21,9 +21,9 @@
 #include <algorithm>
 using namespace llvm;
 
-static bool isFirstClassType(const std::pair<const llvm::Type*,
-                             unsigned int> &P) {
-  return P.first->isFirstClassType();
+static bool isSingleValueType(const std::pair<const llvm::Type*,
+                              unsigned int> &P) {
+  return P.first->isSingleValueType();
 }
 
 static bool isIntegerValue(const std::pair<const Value*, unsigned> &V) {
@@ -103,10 +103,10 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
   // in the table (have low bit-width).
   std::stable_sort(Types.begin(), Types.end(), CompareByFrequency);
     
-  // Partition the Type ID's so that the first-class types occur before the
+  // Partition the Type ID's so that the single-value types occur before the
   // aggregate types.  This allows the aggregate types to be dropped from the
   // type table after parsing the global variable initializers.
-  std::partition(Types.begin(), Types.end(), isFirstClassType);
+  std::partition(Types.begin(), Types.end(), isSingleValueType);
 
   // Now that we rearranged the type table, rebuild TypeMap.
   for (unsigned i = 0, e = Types.size(); i != e; ++i)
@@ -264,11 +264,11 @@ void ValueEnumerator::EnumerateParamAttrs(const PAListPtr &PAL) {
 /// there are none, return -1.
 int ValueEnumerator::PurgeAggregateValues() {
   // If there are no aggregate values at the end of the list, return -1.
-  if (Values.empty() || Values.back().first->getType()->isFirstClassType())
+  if (Values.empty() || Values.back().first->getType()->isSingleValueType())
     return -1;
   
   // Otherwise, remove aggregate values...
-  while (!Values.empty() && !Values.back().first->getType()->isFirstClassType())
+  while (!Values.empty() && !Values.back().first->getType()->isSingleValueType())
     Values.pop_back();
   
   // ... and return the new size.

+ 13 - 0
test/Assembler/insertextractvalue.ll

@@ -0,0 +1,13 @@
+; RUN: llvm-as < %s
+
+;define float @foo({{i32},{float, double}}* %p) {
+  ;%t = load {{i32},{float, double}}* %p
+  ;%s = extractvalue {{i32},{float, double}} %t, i32 1, i32 0
+  ;%r = insertvalue {{i32},{float, double}} %t, double 2.0, i32 1, i32 1
+  ;store {{i32},{float, double}} %r, {{i32},{float, double}}* %p
+  ;ret float %s
+;}
+define float @bar({{i32},{float, double}}* %p) {
+  store {{i32},{float, double}} insertvalue ({{i32},{float, double}}{{i32}{i32 4},{float, double}{float 4.0, double 5.0}}, double 20.0, i32 1, i32 1), {{i32},{float, double}}* %p
+  ret float extractvalue ({{i32},{float, double}}{{i32}{i32 3},{float, double}{float 7.0, double 9.0}}, i32 1, i32 0)
+}

+ 4 - 2
test/Verifier/2006-07-11-StoreStruct.ll

@@ -1,5 +1,7 @@
-; RUN: not llvm-as < %s |& grep {Instruction operands must be first-class}
-; PR826
+; RUN: llvm-as < %s |& not grep {Instruction operands must be first-class}
+
+; This previously was for PR826, but structs are now first-class so
+; the following is now valid.
 
         %struct_4 = type { i32 }
 

+ 6 - 2
utils/llvm.grm

@@ -222,7 +222,9 @@ ConstExpr::= CastOps "(" ^ ConstVal to Types ^ ")"
  | vfcmp FPredicates "(" ^ ConstVal ^ "," ConstVal ^ ")"
  | extractelement "(" ^ ConstVal ^ "," ConstVal ^ ")"
  | insertelement "(" ^ ConstVal ^ "," ConstVal ^ "," ConstVal ^ ")"
- | shufflevector "(" ^ ConstVal ^ "," ConstVal ^ "," ConstVal ^ ")" ;
+ | shufflevector "(" ^ ConstVal ^ "," ConstVal ^ "," ConstVal ^ ")"
+ | extractvalue "(" ^ ConstVal IndexList ^ ")"
+ | insertvalue "(" ^ ConstVal ^ "," ConstVal IndexList ^ ")" ;
 
 ConstVector ::= ConstVector ^ "," ConstVal | ConstVal ;
 
@@ -373,4 +375,6 @@ MemoryInst ::= malloc Types OptCAlign
  | OptVolatile load Types ValueRef OptCAlign
  | OptVolatile store ResolvedVal ^ "," Types ValueRef OptCAlign
  | getresult Types ValueRef ^ "," EUINT64VAL
- | getelementptr Types ValueRef IndexList ;
+ | getelementptr Types ValueRef IndexList
+ | extractvalue Types ValueRef IndexList 
+ | insertvalue Types ValueRef ^ "," Types ValueRef IndexList ;

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است