summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-10-18 05:53:13 +0000
committerChris Lattner <sabre@nondot.org>2003-10-18 05:53:13 +0000
commit99e7ab72c8909469141358552ece13d701d17274 (patch)
treea4ae61d60cbc33bf65861fb839c585de8f23bea3
parent8d1a81d524e3c2a79ffb60c847e486f8536c2e6d (diff)
downloadllvm-99e7ab72c8909469141358552ece13d701d17274.tar.gz
llvm-99e7ab72c8909469141358552ece13d701d17274.tar.bz2
llvm-99e7ab72c8909469141358552ece13d701d17274.tar.xz
New revised variable argument handling support
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9219 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Instruction.def9
-rw-r--r--include/llvm/Intrinsics.h6
-rw-r--r--include/llvm/Support/InstVisitor.h8
-rw-r--r--include/llvm/iOther.h59
-rw-r--r--lib/AsmParser/Lexer.l6
-rw-r--r--lib/AsmParser/llvmAsmParser.y107
6 files changed, 167 insertions, 28 deletions
diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def
index ea3b71d53c..4a78edfccc 100644
--- a/include/llvm/Instruction.def
+++ b/include/llvm/Instruction.def
@@ -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
diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h
index 12cf378f65..dbc0273e89 100644
--- a/include/llvm/Intrinsics.h
+++ b/include/llvm/Intrinsics.h
@@ -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
diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h
index 9934522f45..f8298e313d 100644
--- a/include/llvm/Support/InstVisitor.h
+++ b/include/llvm/Support/InstVisitor.h
@@ -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
diff --git a/include/llvm/iOther.h b/include/llvm/iOther.h
index 787483348f..fa440acffa 100644
--- a/include/llvm/iOther.h
+++ b/include/llvm/iOther.h
@@ -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));
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l
index 6c03d029be..f0f007b4b3 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -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); }
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index b14d6a7ecc..efb9d3e890 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -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 {