Add support for extern varargs methods & varargs method calls


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp
index 3af40f2..f1dcf08 100644
--- a/lib/Bytecode/Reader/InstructionReader.cpp
+++ b/lib/Bytecode/Reader/InstructionReader.cpp
@@ -196,30 +196,48 @@
     Method *M = (Method*)getValue(Raw.Ty, Raw.Arg1);
     if (M == 0) return true;
 
-    const MethodType::ParamTypes &PL = M->getMethodType()->getParamTypes();
-    MethodType::ParamTypes::const_iterator It = PL.begin();
-
     vector<Value *> Params;
-    switch (Raw.NumOperands) {
-    case 0: cerr << "Invalid call instruction encountered!\n";
-	    return true;
-    case 1: break;
-    case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break;
-    case 3: Params.push_back(getValue(*It++, Raw.Arg2)); 
-            if (It == PL.end()) return true;
-            Params.push_back(getValue(*It++, Raw.Arg3)); break;
-    default:
-      Params.push_back(getValue(*It++, Raw.Arg2));
-      {
-        vector<unsigned> &args = *Raw.VarArgs;
-        for (unsigned i = 0; i < args.size(); i++) {
-	  if (It == PL.end()) return true;
-          Params.push_back(getValue(*It++, args[i]));
+    const MethodType::ParamTypes &PL = M->getMethodType()->getParamTypes();
+
+    if (!M->getType()->isMethodType()->isVarArg()) {
+      MethodType::ParamTypes::const_iterator It = PL.begin();
+
+      switch (Raw.NumOperands) {
+      case 0: cerr << "Invalid call instruction encountered!\n";
+	return true;
+      case 1: break;
+      case 2: Params.push_back(getValue(*It++, Raw.Arg2)); break;
+      case 3: Params.push_back(getValue(*It++, Raw.Arg2)); 
+	if (It == PL.end()) return true;
+	Params.push_back(getValue(*It++, Raw.Arg3)); break;
+      default:
+	Params.push_back(getValue(*It++, Raw.Arg2));
+	{
+	  vector<unsigned> &args = *Raw.VarArgs;
+	  for (unsigned i = 0; i < args.size(); i++) {
+	    if (It == PL.end()) return true;
+	    // TODO: Check getValue for null!
+	    Params.push_back(getValue(*It++, args[i]));
+	  }
 	}
+	delete Raw.VarArgs;
+      }
+      if (It != PL.end()) return true;
+    } else {
+      // The first parameter does not have a type specifier... because there
+      // must be at least one concrete argument to a vararg type...
+      Params.push_back(getValue(PL.front(), Raw.Arg2));
+
+      vector<unsigned> &args = *Raw.VarArgs;
+      if ((args.size() & 1) != 0) return true;  // Must be pairs of type/value
+      for (unsigned i = 0; i < args.size(); i+=2) {
+	Value *Ty = getValue(Type::TypeTy, args[i]);
+	if (!Ty) return true;
+	// TODO: Check getValue for null!
+	Params.push_back(getValue(Ty->castTypeAsserting(), args[i+1]));
       }
       delete Raw.VarArgs;
     }
-    if (It != PL.end()) return true;
 
     Res = new CallInst(M, Params);
     return false;