Regenerate.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35174 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer 2007-03-19 18:40:50 +00:00
parent 186a43f1ad
commit 93c40036c8
3 changed files with 613 additions and 585 deletions

File diff suppressed because it is too large Load Diff

View File

@ -299,7 +299,7 @@
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 901 "/proj/llvm/llvm-1/lib/AsmParser/llvmAsmParser.y" #line 932 "/proj/llvm/llvm-1/lib/AsmParser/llvmAsmParser.y"
typedef union YYSTYPE { typedef union YYSTYPE {
llvm::Module *ModuleVal; llvm::Module *ModuleVal;
llvm::Function *FunctionVal; llvm::Function *FunctionVal;

View File

@ -84,13 +84,12 @@ static GlobalVariable *CurGV;
typedef std::vector<Value *> ValueList; // Numbered defs typedef std::vector<Value *> ValueList; // Numbered defs
static void static void
ResolveDefinitions(std::map<const Type *,ValueList> &LateResolvers, ResolveDefinitions(ValueList &LateResolvers, ValueList *FutureLateResolvers=0);
std::map<const Type *,ValueList> *FutureLateResolvers = 0);
static struct PerModuleInfo { static struct PerModuleInfo {
Module *CurrentModule; Module *CurrentModule;
std::map<const Type *, ValueList> Values; // Module level numbered definitions ValueList Values; // Module level numbered definitions
std::map<const Type *,ValueList> LateResolveValues; ValueList LateResolveValues;
std::vector<PATypeHolder> Types; std::vector<PATypeHolder> Types;
std::map<ValID, PATypeHolder> LateResolveTypes; std::map<ValID, PATypeHolder> LateResolveTypes;
@ -208,17 +207,16 @@ static struct PerModuleInfo {
static struct PerFunctionInfo { static struct PerFunctionInfo {
Function *CurrentFunction; // Pointer to current function being created Function *CurrentFunction; // Pointer to current function being created
std::map<const Type*, ValueList> Values; // Keep track of #'d definitions ValueList Values; // Keep track of #'d definitions
std::map<const Type*, ValueList> LateResolveValues; unsigned NextValNum;
ValueList LateResolveValues;
bool isDeclare; // Is this function a forward declararation? bool isDeclare; // Is this function a forward declararation?
GlobalValue::LinkageTypes Linkage; // Linkage for forward declaration. GlobalValue::LinkageTypes Linkage; // Linkage for forward declaration.
GlobalValue::VisibilityTypes Visibility; GlobalValue::VisibilityTypes Visibility;
/// BBForwardRefs - When we see forward references to basic blocks, keep /// BBForwardRefs - When we see forward references to basic blocks, keep
/// track of them here. /// track of them here.
std::map<BasicBlock*, std::pair<ValID, int> > BBForwardRefs; std::map<ValID, BasicBlock*> BBForwardRefs;
std::vector<BasicBlock*> NumberedBlocks;
unsigned NextBBNum;
inline PerFunctionInfo() { inline PerFunctionInfo() {
CurrentFunction = 0; CurrentFunction = 0;
@ -229,16 +227,14 @@ static struct PerFunctionInfo {
inline void FunctionStart(Function *M) { inline void FunctionStart(Function *M) {
CurrentFunction = M; CurrentFunction = M;
NextBBNum = 0; NextValNum = 0;
} }
void FunctionDone() { void FunctionDone() {
NumberedBlocks.clear();
// Any forward referenced blocks left? // Any forward referenced blocks left?
if (!BBForwardRefs.empty()) { if (!BBForwardRefs.empty()) {
GenerateError("Undefined reference to label " + GenerateError("Undefined reference to label " +
BBForwardRefs.begin()->first->getName()); BBForwardRefs.begin()->second->getName());
return; return;
} }
@ -246,6 +242,7 @@ static struct PerFunctionInfo {
ResolveDefinitions(LateResolveValues, &CurModule.LateResolveValues); ResolveDefinitions(LateResolveValues, &CurModule.LateResolveValues);
Values.clear(); // Clear out function local definitions Values.clear(); // Clear out function local definitions
BBForwardRefs.clear();
CurrentFunction = 0; CurrentFunction = 0;
isDeclare = false; isDeclare = false;
Linkage = GlobalValue::ExternalLinkage; Linkage = GlobalValue::ExternalLinkage;
@ -260,14 +257,23 @@ static bool inFunctionScope() { return CurFun.CurrentFunction != 0; }
// Code to handle definitions of all the types // Code to handle definitions of all the types
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static int InsertValue(Value *V, static void InsertValue(Value *V, ValueList &ValueTab = CurFun.Values) {
std::map<const Type*,ValueList> &ValueTab = CurFun.Values) { // Things that have names or are void typed don't get slot numbers
if (V->hasName()) return -1; // Is this a numbered definition? if (V->hasName() || (V->getType() == Type::VoidTy))
return;
// Yes, insert the value into the value table... // In the case of function values, we have to allow for the forward reference
ValueList &List = ValueTab[V->getType()]; // of basic blocks, which are included in the numbering. Consequently, we keep
List.push_back(V); // track of the next insertion location with NextValNum. When a BB gets
return List.size()-1; // inserted, it could change the size of the CurFun.Values vector.
if (&ValueTab == &CurFun.Values) {
if (ValueTab.size() <= CurFun.NextValNum)
ValueTab.resize(CurFun.NextValNum+1);
ValueTab[CurFun.NextValNum++] = V;
return;
}
// For all other lists, its okay to just tack it on the back of the vector.
ValueTab.push_back(V);
} }
static const Type *getTypeVal(const ValID &D, bool DoNotImprovise = false) { static const Type *getTypeVal(const ValID &D, bool DoNotImprovise = false) {
@ -314,11 +320,11 @@ static const Type *getTypeVal(const ValID &D, bool DoNotImprovise = false) {
return Typ; return Typ;
} }
// getValNonImprovising - Look up the value specified by the provided type and // getExistingVal - Look up the value specified by the provided type and
// the provided ValID. If the value exists and has already been defined, return // the provided ValID. If the value exists and has already been defined, return
// it. Otherwise return null. // it. Otherwise return null.
// //
static Value *getValNonImprovising(const Type *Ty, const ValID &D) { static Value *getExistingVal(const Type *Ty, const ValID &D) {
if (isa<FunctionType>(Ty)) { if (isa<FunctionType>(Ty)) {
GenerateError("Functions are not values and " GenerateError("Functions are not values and "
"must be referenced as pointers"); "must be referenced as pointers");
@ -327,26 +333,29 @@ static Value *getValNonImprovising(const Type *Ty, const ValID &D) {
switch (D.Type) { switch (D.Type) {
case ValID::LocalID: { // Is it a numbered definition? case ValID::LocalID: { // Is it a numbered definition?
// Module constants occupy the lowest numbered slots.
std::map<const Type*,ValueList>::iterator VI = CurFun.Values.find(Ty);
// Make sure that our type is within bounds.
if (VI == CurFun.Values.end()) return 0;
// Check that the number is within bounds. // Check that the number is within bounds.
if (D.Num >= VI->second.size()) return 0; if (D.Num >= CurFun.Values.size())
return 0;
return VI->second[D.Num]; Value *Result = CurFun.Values[D.Num];
if (Ty != Result->getType()) {
GenerateError("Numbered value (%" + utostr(D.Num) + ") of type '" +
Result->getType()->getDescription() + "' does not match "
"expected type, '" + Ty->getDescription() + "'");
return 0;
}
return Result;
} }
case ValID::GlobalID: { // Is it a numbered definition? case ValID::GlobalID: { // Is it a numbered definition?
unsigned Num = D.Num; if (D.Num >= CurModule.Values.size())
// Module constants occupy the lowest numbered slots...
std::map<const Type*,ValueList>::iterator VI = CurModule.Values.find(Ty);
if (VI == CurModule.Values.end())
return 0; return 0;
if (D.Num >= VI->second.size()) Value *Result = CurModule.Values[D.Num];
if (Ty != Result->getType()) {
GenerateError("Numbered value (@" + utostr(D.Num) + ") of type '" +
Result->getType()->getDescription() + "' does not match "
"expected type, '" + Ty->getDescription() + "'");
return 0; return 0;
return VI->second[Num]; }
return Result;
} }
case ValID::LocalName: { // Is it a named definition? case ValID::LocalName: { // Is it a named definition?
@ -447,7 +456,7 @@ static Value *getValNonImprovising(const Type *Ty, const ValID &D) {
return 0; return 0;
} }
// getVal - This function is identical to getValNonImprovising, except that if a // getVal - This function is identical to getExistingVal, except that if a
// value is not already defined, it "improvises" by creating a placeholder var // value is not already defined, it "improvises" by creating a placeholder var
// that looks and acts just like the requested variable. When the value is // that looks and acts just like the requested variable. When the value is
// defined later, all uses of the placeholder variable are replaced with the // defined later, all uses of the placeholder variable are replaced with the
@ -460,7 +469,7 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
} }
// See if the value has already been defined. // See if the value has already been defined.
Value *V = getValNonImprovising(Ty, ID); Value *V = getExistingVal(Ty, ID);
if (V) return V; if (V) return V;
if (TriggerError) return 0; if (TriggerError) return 0;
@ -487,69 +496,97 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
return V; return V;
} }
/// getBBVal - This is used for two purposes: /// defineBBVal - This is a definition of a new basic block with the specified
/// * If isDefinition is true, a new basic block with the specified ID is being /// identifier which must be the same as CurFun.NextValNum, if its numeric.
/// defined. static BasicBlock *defineBBVal(const ValID &ID) {
/// * If isDefinition is true, this is a reference to a basic block, which may
/// or may not be a forward reference.
///
static BasicBlock *getBBVal(const ValID &ID, bool isDefinition = false) {
assert(inFunctionScope() && "Can't get basic block at global scope!"); assert(inFunctionScope() && "Can't get basic block at global scope!");
std::string Name;
BasicBlock *BB = 0; BasicBlock *BB = 0;
switch (ID.Type) {
default:
GenerateError("Illegal label reference " + ID.getName());
return 0;
case ValID::LocalID: // Is it a numbered definition?
if (ID.Num >= CurFun.NumberedBlocks.size())
CurFun.NumberedBlocks.resize(ID.Num+1);
BB = CurFun.NumberedBlocks[ID.Num];
break;
case ValID::LocalName: // Is it a named definition?
Name = ID.Name;
Value *N = CurFun.CurrentFunction->getValueSymbolTable().lookup(Name);
if (N && N->getType()->getTypeID() == Type::LabelTyID)
BB = cast<BasicBlock>(N);
break;
}
// See if the block has already been defined. // First, see if this was forward referenced
if (BB) {
// If this is the definition of the block, make sure the existing value was
// just a forward reference. If it was a forward reference, there will be
// an entry for it in the PlaceHolderInfo map.
if (isDefinition && !CurFun.BBForwardRefs.erase(BB)) {
// The existing value was a definition, not a forward reference.
GenerateError("Redefinition of label " + ID.getName());
return 0;
}
ID.destroy(); // Free strdup'd memory. std::map<ValID, BasicBlock*>::iterator BBI = CurFun.BBForwardRefs.find(ID);
return BB; if (BBI != CurFun.BBForwardRefs.end()) {
} BB = BBI->second;
// Otherwise this block has not been seen before.
BB = new BasicBlock("", CurFun.CurrentFunction);
if (ID.Type == ValID::LocalName) {
BB->setName(ID.Name);
} else {
CurFun.NumberedBlocks[ID.Num] = BB;
}
// If this is not a definition, keep track of it so we can use it as a forward
// reference.
if (!isDefinition) {
// Remember where this forward reference came from.
CurFun.BBForwardRefs[BB] = std::make_pair(ID, llvmAsmlineno);
} else {
// The forward declaration could have been inserted anywhere in the // The forward declaration could have been inserted anywhere in the
// function: insert it into the correct place now. // function: insert it into the correct place now.
CurFun.CurrentFunction->getBasicBlockList().remove(BB); CurFun.CurrentFunction->getBasicBlockList().remove(BB);
CurFun.CurrentFunction->getBasicBlockList().push_back(BB); CurFun.CurrentFunction->getBasicBlockList().push_back(BB);
// Erase the forward ref from the map as its no longer "forward"
CurFun.BBForwardRefs.erase(ID);
// If its a numbered definition, bump the number and set the BB value.
if (ID.Type == ValID::LocalID) {
assert(ID.Num == CurFun.NextValNum && "Invalid new block number");
InsertValue(BB);
}
ID.destroy();
return BB;
}
// We haven't seen this BB before and its first mention is a definition.
// Just create it and return it.
std::string Name (ID.Type == ValID::LocalName ? ID.Name : "");
BB = new BasicBlock(Name, CurFun.CurrentFunction);
if (ID.Type == ValID::LocalID) {
assert(ID.Num == CurFun.NextValNum && "Invalid new block number");
InsertValue(BB);
} }
ID.destroy();
ID.destroy(); // Free strdup'd memory
return BB;
}
/// getBBVal - get an existing BB value or create a forward reference for it.
///
static BasicBlock *getBBVal(const ValID &ID) {
assert(inFunctionScope() && "Can't get basic block at global scope!");
BasicBlock *BB = 0;
std::map<ValID, BasicBlock*>::iterator BBI = CurFun.BBForwardRefs.find(ID);
if (BBI != CurFun.BBForwardRefs.end()) {
BB = BBI->second;
} if (ID.Type == ValID::LocalName) {
std::string Name = ID.Name;
Value *N = CurFun.CurrentFunction->getValueSymbolTable().lookup(Name);
if (N)
if (N->getType()->getTypeID() == Type::LabelTyID)
BB = cast<BasicBlock>(N);
else
GenerateError("Reference to label '" + Name + "' is actually of type '"+
N->getType()->getDescription() + "'");
} else if (ID.Type == ValID::LocalID) {
if (ID.Num < CurFun.NextValNum && ID.Num < CurFun.Values.size()) {
if (CurFun.Values[ID.Num]->getType()->getTypeID() == Type::LabelTyID)
BB = cast<BasicBlock>(CurFun.Values[ID.Num]);
else
GenerateError("Reference to label '%" + utostr(ID.Num) +
"' is actually of type '"+
CurFun.Values[ID.Num]->getType()->getDescription() + "'");
}
} else {
GenerateError("Illegal label reference " + ID.getName());
return 0;
}
// If its already been defined, return it now.
if (BB) {
ID.destroy(); // Free strdup'd memory.
return BB;
}
// Otherwise, this block has not been seen before, create it.
std::string Name;
if (ID.Type == ValID::LocalName)
Name = ID.Name;
BB = new BasicBlock(Name, CurFun.CurrentFunction);
// Insert it in the forward refs map.
CurFun.BBForwardRefs[ID] = BB;
return BB; return BB;
} }
@ -571,50 +608,44 @@ static BasicBlock *getBBVal(const ValID &ID, bool isDefinition = false) {
// defs now... // defs now...
// //
static void static void
ResolveDefinitions(std::map<const Type*,ValueList> &LateResolvers, ResolveDefinitions(ValueList &LateResolvers, ValueList *FutureLateResolvers) {
std::map<const Type*,ValueList> *FutureLateResolvers) {
// Loop over LateResolveDefs fixing up stuff that couldn't be resolved // Loop over LateResolveDefs fixing up stuff that couldn't be resolved
for (std::map<const Type*,ValueList>::iterator LRI = LateResolvers.begin(), while (!LateResolvers.empty()) {
E = LateResolvers.end(); LRI != E; ++LRI) { Value *V = LateResolvers.back();
ValueList &List = LRI->second; LateResolvers.pop_back();
while (!List.empty()) {
Value *V = List.back();
List.pop_back();
std::map<Value*, std::pair<ValID, int> >::iterator PHI = std::map<Value*, std::pair<ValID, int> >::iterator PHI =
CurModule.PlaceHolderInfo.find(V); CurModule.PlaceHolderInfo.find(V);
assert(PHI != CurModule.PlaceHolderInfo.end() && "Placeholder error!"); assert(PHI != CurModule.PlaceHolderInfo.end() && "Placeholder error!");
ValID &DID = PHI->second.first; ValID &DID = PHI->second.first;
Value *TheRealValue = getValNonImprovising(LRI->first, DID); Value *TheRealValue = getExistingVal(V->getType(), DID);
if (TriggerError) if (TriggerError)
return;
if (TheRealValue) {
V->replaceAllUsesWith(TheRealValue);
delete V;
CurModule.PlaceHolderInfo.erase(PHI);
} else if (FutureLateResolvers) {
// Functions have their unresolved items forwarded to the module late
// resolver table
InsertValue(V, *FutureLateResolvers);
} else {
if (DID.Type == ValID::LocalName || DID.Type == ValID::GlobalName) {
GenerateError("Reference to an invalid definition: '" +DID.getName()+
"' of type '" + V->getType()->getDescription() + "'",
PHI->second.second);
return; return;
if (TheRealValue) {
V->replaceAllUsesWith(TheRealValue);
delete V;
CurModule.PlaceHolderInfo.erase(PHI);
} else if (FutureLateResolvers) {
// Functions have their unresolved items forwarded to the module late
// resolver table
InsertValue(V, *FutureLateResolvers);
} else { } else {
if (DID.Type == ValID::LocalName || DID.Type == ValID::GlobalName) { GenerateError("Reference to an invalid definition: #" +
GenerateError("Reference to an invalid definition: '" +DID.getName()+ itostr(DID.Num) + " of type '" +
"' of type '" + V->getType()->getDescription() + "'", V->getType()->getDescription() + "'",
PHI->second.second); PHI->second.second);
return; return;
} else {
GenerateError("Reference to an invalid definition: #" +
itostr(DID.Num) + " of type '" +
V->getType()->getDescription() + "'",
PHI->second.second);
return;
}
} }
} }
} }
LateResolvers.clear(); LateResolvers.clear();
} }
@ -688,7 +719,7 @@ ParseGlobalVariable(char *NameStr,
if (!Name.empty()) { if (!Name.empty()) {
ID = ValID::createGlobalName((char*)Name.c_str()); ID = ValID::createGlobalName((char*)Name.c_str());
} else { } else {
ID = ValID::createGlobalID(CurModule.Values[PTy].size()); ID = ValID::createGlobalID(CurModule.Values.size());
} }
if (GlobalValue *FWGV = CurModule.GetForwardRefForGlobal(PTy, ID)) { if (GlobalValue *FWGV = CurModule.GetForwardRefForGlobal(PTy, ID)) {
@ -1631,15 +1662,15 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
// ConstExprs can exist in the body of a function, thus creating // ConstExprs can exist in the body of a function, thus creating
// GlobalValues whenever they refer to a variable. Because we are in // GlobalValues whenever they refer to a variable. Because we are in
// the context of a function, getValNonImprovising will search the functions // the context of a function, getExistingVal will search the functions
// symbol table instead of the module symbol table for the global symbol, // symbol table instead of the module symbol table for the global symbol,
// which throws things all off. To get around this, we just tell // which throws things all off. To get around this, we just tell
// getValNonImprovising that we are at global scope here. // getExistingVal that we are at global scope here.
// //
Function *SavedCurFn = CurFun.CurrentFunction; Function *SavedCurFn = CurFun.CurrentFunction;
CurFun.CurrentFunction = 0; CurFun.CurrentFunction = 0;
Value *V = getValNonImprovising(Ty, $2); Value *V = getExistingVal(Ty, $2);
CHECK_FOR_ERROR CHECK_FOR_ERROR
CurFun.CurrentFunction = SavedCurFn; CurFun.CurrentFunction = SavedCurFn;
@ -2116,7 +2147,7 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
if (!FunctionName.empty()) { if (!FunctionName.empty()) {
ID = ValID::createGlobalName((char*)FunctionName.c_str()); ID = ValID::createGlobalName((char*)FunctionName.c_str());
} else { } else {
ID = ValID::createGlobalID(CurModule.Values[PFT].size()); ID = ValID::createGlobalID(CurModule.Values.size());
} }
Function *Fn = 0; Function *Fn = 0;
@ -2356,7 +2387,6 @@ BasicBlock : InstructionList OptLocalAssign BBTerminatorInst {
CHECK_FOR_ERROR CHECK_FOR_ERROR
InsertValue($3); InsertValue($3);
$1->getInstList().push_back($3); $1->getInstList().push_back($3);
InsertValue($1);
$$ = $1; $$ = $1;
CHECK_FOR_ERROR CHECK_FOR_ERROR
}; };
@ -2370,28 +2400,12 @@ InstructionList : InstructionList Inst {
$$ = $1; $$ = $1;
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| /* empty */ { | /* empty */ { // Empty space between instruction lists
$$ = getBBVal(ValID::createLocalID(CurFun.NextBBNum++), true); $$ = defineBBVal(ValID::createLocalID(CurFun.NextValNum));
CHECK_FOR_ERROR
// Make sure to move the basic block to the correct location in the
// function, instead of leaving it inserted wherever it was first
// referenced.
Function::BasicBlockListType &BBL =
CurFun.CurrentFunction->getBasicBlockList();
BBL.splice(BBL.end(), BBL, $$);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| LABELSTR { | LABELSTR { // Labelled (named) basic block
$$ = getBBVal(ValID::createLocalName($1), true); $$ = defineBBVal(ValID::createLocalName($1));
CHECK_FOR_ERROR
// Make sure to move the basic block to the correct location in the
// function, instead of leaving it inserted wherever it was first
// referenced.
Function::BasicBlockListType &BBL =
CurFun.CurrentFunction->getBasicBlockList();
BBL.splice(BBL.end(), BBL, $$);
CHECK_FOR_ERROR CHECK_FOR_ERROR
}; };
@ -2399,15 +2413,15 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
$$ = new ReturnInst($2); $$ = new ReturnInst($2);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| RET VOID { // Return with no result... | RET VOID { // Return with no result...
$$ = new ReturnInst(); $$ = new ReturnInst();
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| BR LABEL ValueRef { // Unconditional Branch... | BR LABEL ValueRef { // Unconditional Branch...
BasicBlock* tmpBB = getBBVal($3); BasicBlock* tmpBB = getBBVal($3);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = new BranchInst(tmpBB); $$ = new BranchInst(tmpBB);
} // Conditional Branch... } // Conditional Branch...
| BR INTTYPE ValueRef ',' LABEL ValueRef ',' LABEL ValueRef { | BR INTTYPE ValueRef ',' LABEL ValueRef ',' LABEL ValueRef {
assert(cast<IntegerType>($2)->getBitWidth() == 1 && "Not Bool?"); assert(cast<IntegerType>($2)->getBitWidth() == 1 && "Not Bool?");
BasicBlock* tmpBBA = getBBVal($6); BasicBlock* tmpBBA = getBBVal($6);
@ -2526,7 +2540,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef { JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef {
$$ = $1; $$ = $1;
Constant *V = cast<Constant>(getValNonImprovising($2, $3)); Constant *V = cast<Constant>(getExistingVal($2, $3));
CHECK_FOR_ERROR CHECK_FOR_ERROR
if (V == 0) if (V == 0)
GEN_ERROR("May only switch on a constant pool value"); GEN_ERROR("May only switch on a constant pool value");
@ -2537,7 +2551,7 @@ JumpTable : JumpTable IntType ConstValueRef ',' LABEL ValueRef {
} }
| IntType ConstValueRef ',' LABEL ValueRef { | IntType ConstValueRef ',' LABEL ValueRef {
$$ = new std::vector<std::pair<Constant*, BasicBlock*> >(); $$ = new std::vector<std::pair<Constant*, BasicBlock*> >();
Constant *V = cast<Constant>(getValNonImprovising($1, $2)); Constant *V = cast<Constant>(getExistingVal($1, $2));
CHECK_FOR_ERROR CHECK_FOR_ERROR
if (V == 0) if (V == 0)