New revised variable argument handling support
authorChris Lattner <sabre@nondot.org>
Sat, 18 Oct 2003 05:53:13 +0000 (05:53 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 18 Oct 2003 05:53:13 +0000 (05:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9219 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Instruction.def
include/llvm/Intrinsics.h
include/llvm/Support/InstVisitor.h
include/llvm/iOther.h
lib/AsmParser/Lexer.l
lib/AsmParser/llvmAsmParser.y

index ea3b71d53c8a1bcf81839964eb072a44256056b3..4a78edfccc6c3aa3fb419f286040d8b5cce8776b 100644 (file)
@@ -120,11 +120,12 @@ HANDLE_OTHER_INST(28, Call   , CallInst   )  // Call a function
 
 HANDLE_OTHER_INST(29, Shl    , ShiftInst  )  // Shift operations
 HANDLE_OTHER_INST(30, Shr    , ShiftInst  )
-HANDLE_OTHER_INST(31, VarArg , VarArgInst )  // va_arg instruction
+HANDLE_OTHER_INST(31, VANext , VANextInst )  // vanext instruction
+HANDLE_OTHER_INST(32, VAArg  , VAArgInst  )  // vaarg  instruction
 
-HANDLE_OTHER_INST(32, UserOp1, Instruction)  // May be used internally in a pass
-HANDLE_OTHER_INST(33, UserOp2, Instruction)
-  LAST_OTHER_INST(33)
+HANDLE_OTHER_INST(33, UserOp1, Instruction)  // May be used internally in a pass
+HANDLE_OTHER_INST(34, UserOp2, Instruction)
+  LAST_OTHER_INST(34)
 
 #undef  FIRST_TERM_INST
 #undef HANDLE_TERM_INST
index 12cf378f651c12684588ba187dcd4f8e3d83fdc6..dbc0273e89721e14581b1fc0015bccbb07db694f 100644 (file)
@@ -18,9 +18,9 @@ namespace LLVMIntrinsic {
     not_intrinsic = 0,   // Must be zero
 
     // Varargs handling intrinsics...
-    va_start,       // Used to represent a va_start call in C
-    va_end,         // Used to represent a va_end call in C
-    va_copy,        // Used to represent a va_copy call in C
+    va_start,       // Used to implement the va_start macro in C
+    va_end,         // Used to implement the va_end macro in C
+    va_copy,        // Used to implement the va_copy macro in C
 
     // Setjmp/Longjmp intrinsics...
     setjmp,         // Used to represent a setjmp call in C
index 9934522f4565ec01a4853246e5bf28e3b4b28016..f8298e313d83d94e891bf555ec560af61a1d0d8f 100644 (file)
@@ -136,7 +136,7 @@ struct InstVisitor {
   //
 #define HANDLE_INST(NUM, OPCODE, CLASS) \
     RetTy visit##OPCODE(CLASS &I) { DELEGATE(CLASS); }
-#define HANDLE_OTHER_INST(NUM, OPCODE, CLASS)   // Ignore "other" instructions
+#define HANDLE_OTHER_INST(NUM, OPCODE, CLASS)  // Handle "other" insts specially
 #include "llvm/Instruction.def"
 
   // Implement all "other" instructions, except for PHINode
@@ -144,7 +144,8 @@ struct InstVisitor {
   RetTy visitCall(CallInst &I)       { DELEGATE(CallInst);    }
   RetTy visitShr(ShiftInst &I)       { DELEGATE(ShiftInst);   }
   RetTy visitShl(ShiftInst &I)       { DELEGATE(ShiftInst);   }
-  RetTy visitVarArg(VarArgInst &I)   { DELEGATE(VarArgInst);  }
+  RetTy visitVANext(VANextInst &I)   { DELEGATE(VANextInst);  }
+  RetTy visitVAArg (VAArgInst &I)    { DELEGATE(VAArgInst);  }
   RetTy visitUserOp1(Instruction &I) { DELEGATE(Instruction); }
   RetTy visitUserOp2(Instruction &I) { DELEGATE(Instruction); }
 
@@ -168,7 +169,8 @@ struct InstVisitor {
   RetTy visitCastInst(CastInst     &I)              { DELEGATE(Instruction); }
   RetTy visitCallInst(CallInst     &I)              { DELEGATE(Instruction); }
   RetTy visitShiftInst(ShiftInst   &I)              { DELEGATE(Instruction); }
-  RetTy visitVarArgInst(VarArgInst &I)              { DELEGATE(Instruction); }
+  RetTy visitVANextInst(VANextInst &I)              { DELEGATE(Instruction); }
+  RetTy visitVAArgInst(VAArgInst   &I)              { DELEGATE(Instruction); }
 
   // Next level propagators... if the user does not overload a specific
   // instruction type, they can overload one of these to get the whole class
index 787483348fb9ebdf0184f0649cf62cfcca02dacb..fa440acffa0cfb1e13b620dd5acbf2012065bd13 100644 (file)
@@ -123,34 +123,67 @@ public:
 
 
 //===----------------------------------------------------------------------===//
-//                               VarArgInst Class
+//                                VANextInst Class
 //===----------------------------------------------------------------------===//
 
-/// VarArgInst - This class represents the va_arg llvm instruction, which reads
-/// an argument of the destination type from the va_list operand pointed to by
-/// the only operand.
+/// VANextInst - This class represents the va_next llvm instruction, which
+/// advances a vararg list passed an argument of the specified type, returning
+/// the resultant list.
 ///
-class VarArgInst : public Instruction {
-  VarArgInst(const VarArgInst &VAI) : Instruction(VAI.getType(), VarArg) {
+class VANextInst : public Instruction {
+  PATypeHolder ArgTy;
+  VANextInst(const VANextInst &VAN)
+    : Instruction(VAN.getType(), VANext), ArgTy(VAN.getArgType()) {
     Operands.reserve(1);
-    Operands.push_back(Use(VAI.Operands[0], this));
+    Operands.push_back(Use(VAN.Operands[0], this));
   }
 public:
-  VarArgInst(Value *S, const Type *Ty, const std::string &Name = "",
+  VANextInst(Value *List, const Type *Ty, const std::string &Name = "",
              Instruction *InsertBefore = 0)
-    : Instruction(Ty, VarArg, Name, InsertBefore) {
+    : Instruction(List->getType(), VANext, Name, InsertBefore), ArgTy(Ty) {
     Operands.reserve(1);
-    Operands.push_back(Use(S, this));
+    Operands.push_back(Use(List, this));
+  }
+
+  const Type *getArgType() const { return ArgTy; }
+
+  virtual Instruction *clone() const { return new VANextInst(*this); }
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const VANextInst *) { return true; }
+  static inline bool classof(const Instruction *I) {
+    return I->getOpcode() == VANext;
+  }
+  static inline bool classof(const Value *V) {
+    return isa<Instruction>(V) && classof(cast<Instruction>(V));
+  }
+};
+
+/// VAArgInst - This class represents the va_arg llvm instruction, which returns
+/// an argument of the specified type given a va_list.
+///
+class VAArgInst : public Instruction {
+  VAArgInst(const VAArgInst &VAA)
+    : Instruction(VAA.getType(), VAArg) {
+    Operands.reserve(1);
+    Operands.push_back(Use(VAA.Operands[0], this));
+  }
+public:
+  VAArgInst(Value *List, const Type *Ty, const std::string &Name = "",
+             Instruction *InsertBefore = 0)
+    : Instruction(Ty, VAArg, Name, InsertBefore) {
+    Operands.reserve(1);
+    Operands.push_back(Use(List, this));
   }
 
-  virtual Instruction *clone() const { return new VarArgInst(*this); }
+  virtual Instruction *clone() const { return new VAArgInst(*this); }
 
   bool mayWriteToMemory() const { return true; }
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
-  static inline bool classof(const VarArgInst *) { return true; }
+  static inline bool classof(const VAArgInst *) { return true; }
   static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == VarArg;
+    return I->getOpcode() == VAArg;
   }
   static inline bool classof(const Value *V) {
     return isa<Instruction>(V) && classof(cast<Instruction>(V));
index 6c03d029be9a4b7a72d5c487b6c588c065f2921e..f0f007b4b3a1fb6ad59940d12dc50198853a7ea9 100644 (file)
@@ -129,7 +129,7 @@ VarID       %[-a-zA-Z$._][-a-zA-Z$._0-9]*
 Label       [-a-zA-Z$._0-9]+:
 
 /* Quoted names can contain any character except " and \ */
-StringConstant \"[^\"]+\"
+StringConstant \"[^\"]*\"
 
 
 /* [PN]Integer: match positive and negative literal integer values that
@@ -224,7 +224,9 @@ call            { RET_TOK(OtherOpVal, Call, CALL); }
 cast            { RET_TOK(OtherOpVal, Cast, CAST); }
 shl             { RET_TOK(OtherOpVal, Shl, SHL); }
 shr             { RET_TOK(OtherOpVal, Shr, SHR); }
-va_arg          { RET_TOK(OtherOpVal, VarArg, VA_ARG); }
+va_arg          { return VA_ARG; /* FIXME: OBSOLETE */}
+vanext          { RET_TOK(OtherOpVal, VANext, VANEXT); }
+vaarg           { RET_TOK(OtherOpVal, VAArg , VAARG); }
 
 ret             { RET_TOK(TermOpVal, Ret, RET); }
 br              { RET_TOK(TermOpVal, Br, BR); }
index b14d6a7ecc08d2ea9f61f2ba238a2a70a69a92e3..efb9d3e8909db53ca459824696905665533a7c06 100644 (file)
@@ -37,6 +37,14 @@ std::string CurFilename;
 
 #define YYERROR_VERBOSE 1
 
+// HACK ALERT: This variable is used to implement the automatic conversion of
+// variable argument instructions from their old to new forms.  When this
+// compatiblity "Feature" is removed, this should be too.
+//
+static BasicBlock *CurBB;
+static bool ObsoleteVarArgs;
+
+
 // This contains info used when building the body of a function.  It is
 // destroyed when the function is completed.
 //
@@ -595,11 +603,76 @@ Module *RunVMAsmParser(const std::string &Filename, FILE *F) {
   llvmAsmin = F;
   CurFilename = Filename;
   llvmAsmlineno = 1;      // Reset the current line number...
+  ObsoleteVarArgs = false;
 
   // Allocate a new module to read
   CurModule.CurrentModule = new Module(Filename);
   yyparse();       // Parse the file.
+
   Module *Result = ParserResult;
+
+  // Check to see if they called va_start but not va_arg..
+  if (!ObsoleteVarArgs)
+    if (Function *F = Result->getNamedFunction("llvm.va_start"))
+      if (F->asize() == 1) {
+        std::cerr << "WARNING: this file uses obsolete features.  "
+                  << "Assemble and disassemble to update it.\n";
+        ObsoleteVarArgs = true;
+      }
+
+
+  if (ObsoleteVarArgs) {
+    // If the user is making use of obsolete varargs intrinsics, adjust them for
+    // the user.
+    if (Function *F = Result->getNamedFunction("llvm.va_start")) {
+      assert(F->asize() == 1 && "Obsolete va_start takes 1 argument!");
+
+      const Type *RetTy = F->getFunctionType()->getParamType(0);
+      RetTy = cast<PointerType>(RetTy)->getElementType();
+      Function *NF = Result->getOrInsertFunction("llvm.va_start", RetTy, 0);
+      
+      while (!F->use_empty()) {
+        CallInst *CI = cast<CallInst>(F->use_back());
+        Value *V = new CallInst(NF, "", CI);
+        new StoreInst(V, CI->getOperand(1), CI);
+        CI->getParent()->getInstList().erase(CI);
+      }
+      Result->getFunctionList().erase(F);
+    }
+    
+    if (Function *F = Result->getNamedFunction("llvm.va_end")) {
+      assert(F->asize() == 1 && "Obsolete va_end takes 1 argument!");
+      const Type *ArgTy = F->getFunctionType()->getParamType(0);
+      ArgTy = cast<PointerType>(ArgTy)->getElementType();
+      Function *NF = Result->getOrInsertFunction("llvm.va_end", Type::VoidTy,
+                                                 ArgTy, 0);
+
+      while (!F->use_empty()) {
+        CallInst *CI = cast<CallInst>(F->use_back());
+        Value *V = new LoadInst(CI->getOperand(1), "", CI);
+        new CallInst(NF, V, "", CI);
+        CI->getParent()->getInstList().erase(CI);
+      }
+      Result->getFunctionList().erase(F);
+    }
+
+    if (Function *F = Result->getNamedFunction("llvm.va_copy")) {
+      assert(F->asize() == 2 && "Obsolete va_copy takes 2 argument!");
+      const Type *ArgTy = F->getFunctionType()->getParamType(0);
+      ArgTy = cast<PointerType>(ArgTy)->getElementType();
+      Function *NF = Result->getOrInsertFunction("llvm.va_copy", ArgTy,
+                                                 ArgTy, 0);
+
+      while (!F->use_empty()) {
+        CallInst *CI = cast<CallInst>(F->use_back());
+        Value *V = new CallInst(NF, CI->getOperand(2), "", CI);
+        new StoreInst(V, CI->getOperand(1), CI);
+        CI->getParent()->getInstList().erase(CI);
+      }
+      Result->getFunctionList().erase(F);
+    }
+  }
+
   llvmAsmin = stdin;    // F is about to go away, don't use it anymore...
   ParserResult = 0;
 
@@ -712,7 +785,8 @@ Module *RunVMAsmParser(const std::string &Filename, FILE *F) {
 
 // Other Operators
 %type  <OtherOpVal> ShiftOps
-%token <OtherOpVal> PHI CALL CAST SHL SHR VA_ARG
+%token <OtherOpVal> PHI CALL CAST SHL SHR VAARG VANEXT
+%token VA_ARG // FIXME: OBSOLETE
 
 %start Module
 %%
@@ -1452,7 +1526,7 @@ InstructionList : InstructionList Inst {
     $$ = $1;
   }
   | /* empty */ {
-    $$ = new BasicBlock();
+    $$ = CurBB = new BasicBlock();
   };
 
 BBTerminatorInst : RET ResolvedVal {              // Return with a result...
@@ -1643,7 +1717,34 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     delete $4;
   }
   | VA_ARG ResolvedVal ',' Types {
-    $$ = new VarArgInst($2, *$4);
+    // FIXME: This is emulation code for an obsolete syntax.  This should be
+    // removed at some point.
+    if (!ObsoleteVarArgs) {
+      std::cerr << "WARNING: this file uses obsolete features.  "
+                << "Assemble and disassemble to update it.\n";
+      ObsoleteVarArgs = true;
+    }
+
+    // First, load the valist...
+    Instruction *CurVAList = new LoadInst($2, "");
+    CurBB->getInstList().push_back(CurVAList);
+
+    // Emit the vaarg instruction.
+    $$ = new VAArgInst(CurVAList, *$4);
+    
+    // Now we must advance the pointer and update it in memory.
+    Instruction *TheVANext = new VANextInst(CurVAList, *$4);
+    CurBB->getInstList().push_back(TheVANext);
+
+    CurBB->getInstList().push_back(new StoreInst(TheVANext, $2));
+    delete $4;
+  }
+  | VAARG ResolvedVal ',' Types {
+    $$ = new VAArgInst($2, *$4);
+    delete $4;
+  }
+  | VANEXT ResolvedVal ',' Types {
+    $$ = new VANextInst($2, *$4);
     delete $4;
   }
   | PHI PHIList {