}
void writeOperand(const Value *Operand);
+ void writeOperandInternal(const Value *Operand);
string getValueName(const Value *V);
void printFunction(Function *);
+ // isInlinableInst - Attempt to inline instructions into their uses to build
+ // trees as much as possible. To do this, we have to consistently decide
+ // what is acceptable to inline, so that variable declarations don't get
+ // printed and an extra copy of the expr is not emitted.
+ //
+ static bool isInlinableInst(Instruction *I) {
+ // Must be an expression, must be used exactly once. If it is dead, we
+ // emit it inline where it would go.
+ if (I->getType() == Type::VoidTy || I->use_size() != 1 ||
+ isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I))
+ return false;
+
+ // Only inline instruction it it's use is in the same BB as the inst.
+ return I->getParent() == cast<Instruction>(I->use_back())->getParent();
+ }
+
// Instruction visitation functions
friend class InstVisitor<CWriter>;
return "ltmp_" + itostr(Slot) + "_" + utostr(V->getType()->getUniqueID());
}
-void CWriter::writeOperand(const Value *Operand) {
- if (isa<GlobalVariable>(Operand))
- Out << "(&"; // Global variables are references as their addresses by llvm
-
+void CWriter::writeOperandInternal(const Value *Operand) {
if (Operand->hasName()) {
Out << getValueName(Operand);
} else if (const Constant *CPV = dyn_cast<const Constant>(Operand)) {
assert(Slot >= 0 && "Malformed LLVM!");
Out << "ltmp_" << Slot << "_" << Operand->getType()->getUniqueID();
}
+}
+
+void CWriter::writeOperand(const Value *Operand) {
+ if (Instruction *I = dyn_cast<Instruction>(Operand))
+ if (isInlinableInst(I)) {
+ // Should we inline this instruction to build a tree?
+ Out << "(";
+ visit(I);
+ Out << ")";
+ return;
+ }
+
+ if (isa<GlobalVariable>(Operand))
+ Out << "(&"; // Global variables are references as their addresses by llvm
+
+ writeOperandInternal(Operand);
if (isa<GlobalVariable>(Operand))
Out << ")";
// print local variable information for the function
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
- if ((*I)->getType() != Type::VoidTy) {
+ if ((*I)->getType() != Type::VoidTy && !isInlinableInst(*I)) {
Out << " ";
printTypeVar((*I)->getType(), getValueName(*I));
Out << ";\n";
if (NeedsLabel) Out << getValueName(BB) << ":\n";
// Output all of the instructions in the basic block...
- // print the basic blocks
- visit(BB);
+ for (BasicBlock::iterator II = BB->begin(), E = BB->end()-1;
+ II != E; ++II) {
+ if (!isInlinableInst(*II) && !isa<PHINode>(*II)) {
+ Instruction *I = *II;
+ if (I->getType() != Type::VoidTy)
+ outputLValue(I);
+ else
+ Out << " ";
+ visit(I);
+ Out << ";\n";
+ }
+ }
+
+ // Don't emit prefix or suffix for the terminator...
+ visit(BB->getTerminator());
}
Out << "}\n\n";
void CWriter::visitNot(GenericUnaryInst *I) {
- outputLValue(I);
Out << "~";
writeOperand(I->getOperand(0));
- Out << ";\n";
}
void CWriter::visitBinaryOperator(Instruction *I) {
// binary instructions, shift instructions, setCond instructions.
- outputLValue(I);
if (isa<PointerType>(I->getType())) {
Out << "(";
printType(I->getType());
if (isa<PointerType>(I->getType())) Out << "(long long)";
writeOperand(I->getOperand(1));
- Out << ";\n";
}
void CWriter::visitCastInst(CastInst *I) {
- outputLValue(I);
Out << "(";
printType(I->getType());
Out << ")";
writeOperand(I->getOperand(0));
- Out << ";\n";
}
void CWriter::visitCallInst(CallInst *I) {
- if (I->getType() != Type::VoidTy)
- outputLValue(I);
- else
- Out << " ";
-
const PointerType *PTy = cast<PointerType>(I->getCalledValue()->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType();
writeOperand(I->getOperand(op));
}
}
- Out << ");\n";
+ Out << ")";
}
void CWriter::visitMallocInst(MallocInst *I) {
- outputLValue(I);
Out << "(";
printType(I->getType());
Out << ")malloc(sizeof(";
Out << " * " ;
writeOperand(I->getOperand(0));
}
- Out << ");\n";
+ Out << ")";
}
void CWriter::visitAllocaInst(AllocaInst *I) {
- outputLValue(I);
Out << "(";
printType(I->getType());
Out << ") alloca(sizeof(";
Out << " * " ;
writeOperand(I->getOperand(0));
}
- Out << ");\n";
+ Out << ")";
}
void CWriter::visitFreeInst(FreeInst *I) {
- Out << " free(";
+ Out << "free(";
writeOperand(I->getOperand(0));
- Out << ");\n";
+ Out << ")";
}
void CWriter::printIndexingExpr(MemAccessInst *MAI) {
MemAccessInst::op_iterator I = MAI->idx_begin(), E = MAI->idx_end();
- if (I == E)
+ if (I == E) {
+ // If accessing a global value with no indexing, avoid *(&GV) syndrome
+ if (GlobalValue *V = dyn_cast<GlobalValue>(MAI->getPointerOperand())) {
+ writeOperandInternal(V);
+ return;
+ }
+
Out << "*"; // Implicit zero first argument: '*x' is equivalent to 'x[0]'
+ }
writeOperand(MAI->getPointerOperand());
Constant *CI = dyn_cast<Constant>(*I);
if (CI && CI->isNullValue() && I+1 != E &&
(*(I+1))->getType() == Type::UByteTy) {
- ++I;
- Out << "->field" << cast<ConstantUInt>(*I)->getValue();
- ++I;
+ Out << "->field" << cast<ConstantUInt>(*(I+1))->getValue();
+ I += 2;
}
for (; I != E; ++I)
}
void CWriter::visitLoadInst(LoadInst *I) {
- outputLValue(I);
printIndexingExpr(I);
- Out << ";\n";
}
void CWriter::visitStoreInst(StoreInst *I) {
- Out << " ";
printIndexingExpr(I);
Out << " = ";
writeOperand(I->getOperand(0));
- Out << ";\n";
}
void CWriter::visitGetElementPtrInst(GetElementPtrInst *I) {
- outputLValue(I);
Out << "&";
printIndexingExpr(I);
- Out << ";\n";
}
//===----------------------------------------------------------------------===//
}
void writeOperand(const Value *Operand);
+ void writeOperandInternal(const Value *Operand);
string getValueName(const Value *V);
void printFunction(Function *);
+ // isInlinableInst - Attempt to inline instructions into their uses to build
+ // trees as much as possible. To do this, we have to consistently decide
+ // what is acceptable to inline, so that variable declarations don't get
+ // printed and an extra copy of the expr is not emitted.
+ //
+ static bool isInlinableInst(Instruction *I) {
+ // Must be an expression, must be used exactly once. If it is dead, we
+ // emit it inline where it would go.
+ if (I->getType() == Type::VoidTy || I->use_size() != 1 ||
+ isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I))
+ return false;
+
+ // Only inline instruction it it's use is in the same BB as the inst.
+ return I->getParent() == cast<Instruction>(I->use_back())->getParent();
+ }
+
// Instruction visitation functions
friend class InstVisitor<CWriter>;
return "ltmp_" + itostr(Slot) + "_" + utostr(V->getType()->getUniqueID());
}
-void CWriter::writeOperand(const Value *Operand) {
- if (isa<GlobalVariable>(Operand))
- Out << "(&"; // Global variables are references as their addresses by llvm
-
+void CWriter::writeOperandInternal(const Value *Operand) {
if (Operand->hasName()) {
Out << getValueName(Operand);
} else if (const Constant *CPV = dyn_cast<const Constant>(Operand)) {
assert(Slot >= 0 && "Malformed LLVM!");
Out << "ltmp_" << Slot << "_" << Operand->getType()->getUniqueID();
}
+}
+
+void CWriter::writeOperand(const Value *Operand) {
+ if (Instruction *I = dyn_cast<Instruction>(Operand))
+ if (isInlinableInst(I)) {
+ // Should we inline this instruction to build a tree?
+ Out << "(";
+ visit(I);
+ Out << ")";
+ return;
+ }
+
+ if (isa<GlobalVariable>(Operand))
+ Out << "(&"; // Global variables are references as their addresses by llvm
+
+ writeOperandInternal(Operand);
if (isa<GlobalVariable>(Operand))
Out << ")";
// print local variable information for the function
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
- if ((*I)->getType() != Type::VoidTy) {
+ if ((*I)->getType() != Type::VoidTy && !isInlinableInst(*I)) {
Out << " ";
printTypeVar((*I)->getType(), getValueName(*I));
Out << ";\n";
if (NeedsLabel) Out << getValueName(BB) << ":\n";
// Output all of the instructions in the basic block...
- // print the basic blocks
- visit(BB);
+ for (BasicBlock::iterator II = BB->begin(), E = BB->end()-1;
+ II != E; ++II) {
+ if (!isInlinableInst(*II) && !isa<PHINode>(*II)) {
+ Instruction *I = *II;
+ if (I->getType() != Type::VoidTy)
+ outputLValue(I);
+ else
+ Out << " ";
+ visit(I);
+ Out << ";\n";
+ }
+ }
+
+ // Don't emit prefix or suffix for the terminator...
+ visit(BB->getTerminator());
}
Out << "}\n\n";
void CWriter::visitNot(GenericUnaryInst *I) {
- outputLValue(I);
Out << "~";
writeOperand(I->getOperand(0));
- Out << ";\n";
}
void CWriter::visitBinaryOperator(Instruction *I) {
// binary instructions, shift instructions, setCond instructions.
- outputLValue(I);
if (isa<PointerType>(I->getType())) {
Out << "(";
printType(I->getType());
if (isa<PointerType>(I->getType())) Out << "(long long)";
writeOperand(I->getOperand(1));
- Out << ";\n";
}
void CWriter::visitCastInst(CastInst *I) {
- outputLValue(I);
Out << "(";
printType(I->getType());
Out << ")";
writeOperand(I->getOperand(0));
- Out << ";\n";
}
void CWriter::visitCallInst(CallInst *I) {
- if (I->getType() != Type::VoidTy)
- outputLValue(I);
- else
- Out << " ";
-
const PointerType *PTy = cast<PointerType>(I->getCalledValue()->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType();
writeOperand(I->getOperand(op));
}
}
- Out << ");\n";
+ Out << ")";
}
void CWriter::visitMallocInst(MallocInst *I) {
- outputLValue(I);
Out << "(";
printType(I->getType());
Out << ")malloc(sizeof(";
Out << " * " ;
writeOperand(I->getOperand(0));
}
- Out << ");\n";
+ Out << ")";
}
void CWriter::visitAllocaInst(AllocaInst *I) {
- outputLValue(I);
Out << "(";
printType(I->getType());
Out << ") alloca(sizeof(";
Out << " * " ;
writeOperand(I->getOperand(0));
}
- Out << ");\n";
+ Out << ")";
}
void CWriter::visitFreeInst(FreeInst *I) {
- Out << " free(";
+ Out << "free(";
writeOperand(I->getOperand(0));
- Out << ");\n";
+ Out << ")";
}
void CWriter::printIndexingExpr(MemAccessInst *MAI) {
MemAccessInst::op_iterator I = MAI->idx_begin(), E = MAI->idx_end();
- if (I == E)
+ if (I == E) {
+ // If accessing a global value with no indexing, avoid *(&GV) syndrome
+ if (GlobalValue *V = dyn_cast<GlobalValue>(MAI->getPointerOperand())) {
+ writeOperandInternal(V);
+ return;
+ }
+
Out << "*"; // Implicit zero first argument: '*x' is equivalent to 'x[0]'
+ }
writeOperand(MAI->getPointerOperand());
Constant *CI = dyn_cast<Constant>(*I);
if (CI && CI->isNullValue() && I+1 != E &&
(*(I+1))->getType() == Type::UByteTy) {
- ++I;
- Out << "->field" << cast<ConstantUInt>(*I)->getValue();
- ++I;
+ Out << "->field" << cast<ConstantUInt>(*(I+1))->getValue();
+ I += 2;
}
for (; I != E; ++I)
}
void CWriter::visitLoadInst(LoadInst *I) {
- outputLValue(I);
printIndexingExpr(I);
- Out << ";\n";
}
void CWriter::visitStoreInst(StoreInst *I) {
- Out << " ";
printIndexingExpr(I);
Out << " = ";
writeOperand(I->getOperand(0));
- Out << ";\n";
}
void CWriter::visitGetElementPtrInst(GetElementPtrInst *I) {
- outputLValue(I);
Out << "&";
printIndexingExpr(I);
- Out << ";\n";
}
//===----------------------------------------------------------------------===//