Move ConstantExpr handling to ResolveConstantExpr method and also

add support for PtrToInt, Add, Mul.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78552 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes 2009-08-10 03:32:40 +00:00
parent e8af1f9afe
commit 64a6b39417
2 changed files with 87 additions and 28 deletions

View File

@ -497,32 +497,21 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
EmitGlobalConstant(CP->getOperand(I), GblS);
return;
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
switch (CE->getOpcode()) {
case Instruction::BitCast: {
EmitGlobalConstant(CE->getOperand(0), GblS);
return;
}
case Instruction::GetElementPtr: {
const Constant *ptrVal = CE->getOperand(0);
SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end());
int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0],
idxVec.size());
EmitGlobalDataRelocation(cast<const GlobalValue>(ptrVal),
TD->getTypeAllocSize(ptrVal->getType()),
GblS, Offset);
return;
}
case Instruction::IntToPtr: {
Constant *Op = CE->getOperand(0);
Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(), false/*ZExt*/);
// Resolve a constant expression which returns a (Constant, Offset)
// pair. If 'Res.first' is a GlobalValue, emit a relocation with
// the offset 'Res.second', otherwise emit a global constant like
// it is always done for not contant expression types.
CstExprResTy Res = ResolveConstantExpr(CE);
const Constant *Op = Res.first;
if (isa<GlobalValue>(Op))
EmitGlobalDataRelocation(cast<const GlobalValue>(Op),
TD->getTypeAllocSize(Op->getType()),
GblS, Res.second);
else
EmitGlobalConstant(Op, GblS);
return;
}
}
std::string msg(CE->getOpcodeName());
raw_string_ostream ErrorMsg(msg);
ErrorMsg << ": Unsupported ConstantExpr type";
llvm_report_error(ErrorMsg.str());
} else if (CV->getType()->getTypeID() == Type::PointerTyID) {
// Fill the data entry with zeros or emit a relocation entry
if (isa<ConstantPointerNull>(CV))
@ -544,8 +533,77 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
llvm_report_error(ErrorMsg.str());
}
// ResolveConstantExpr - Resolve the constant expression until it stop
// yielding other constant expressions.
CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) {
const TargetData *TD = TM.getTargetData();
// There ins't constant expression inside others anymore
if (!isa<ConstantExpr>(CV))
return std::make_pair(CV, 0);
const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
switch (CE->getOpcode()) {
case Instruction::BitCast:
return ResolveConstantExpr(CE->getOperand(0));
case Instruction::GetElementPtr: {
const Constant *ptrVal = CE->getOperand(0);
SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end());
int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0],
idxVec.size());
return std::make_pair(ptrVal, Offset);
}
case Instruction::IntToPtr: {
Constant *Op = CE->getOperand(0);
Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(), false/*ZExt*/);
return ResolveConstantExpr(Op);
}
case Instruction::PtrToInt: {
Constant *Op = CE->getOperand(0);
const Type *Ty = CE->getType();
// We can emit the pointer value into this slot if the slot is an
// integer slot greater or equal to the size of the pointer.
if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType()))
return ResolveConstantExpr(Op);
llvm_unreachable("Integer size less then pointer size");
}
case Instruction::Add:
case Instruction::Sub: {
// Only handle cases where there's a constant expression with GlobalValue
// as first operand and ConstantInt as second, which are the cases we can
// solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1
// 1) Instruction::Add => (global) + CstInt
// 2) Instruction::Sub => (global) + -CstInt
const Constant *Op0 = CE->getOperand(0);
const Constant *Op1 = CE->getOperand(1);
assert(isa<ConstantInt>(Op1) && "Op1 must be a ConstantInt");
CstExprResTy Res = ResolveConstantExpr(Op0);
assert(isa<GlobalValue>(Res.first) && "Op0 must be a GlobalValue");
const APInt &RHS = cast<ConstantInt>(Op1)->getValue();
switch (CE->getOpcode()) {
case Instruction::Add:
return std::make_pair(Res.first, RHS.getSExtValue());
case Instruction::Sub:
return std::make_pair(Res.first, (-RHS).getSExtValue());
}
}
}
std::string msg(CE->getOpcodeName());
raw_string_ostream ErrorMsg(msg);
ErrorMsg << ": Unsupported ConstantExpr type";
llvm_report_error(ErrorMsg.str());
return std::make_pair(CV, 0); // silence warning
}
void ELFWriter::EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size,
ELFSection &GblS, uint64_t Offset) {
ELFSection &GblS, int64_t Offset) {
// Create the relocation entry for the global value
MachineRelocation MR =
MachineRelocation::getGV(GblS.getCurrentPCOffset(),
@ -868,7 +926,6 @@ void ELFWriter::EmitStringTable(const std::string &ModuleName) {
std::string Name;
if (Sym.isGlobalValue())
// Use the name mangler to uniquify the LLVM symbol.
Name.append(Mang->getMangledName(Sym.getGlobalValue()));
else if (Sym.isExternalSym())
Name.append(Sym.getExternalSymbol());

View File

@ -43,6 +43,7 @@ namespace llvm {
typedef std::vector<ELFSection*>::iterator ELFSectionIter;
typedef SetVector<const GlobalValue*>::const_iterator PendingGblsIter;
typedef SetVector<const char *>::const_iterator PendingExtsIter;
typedef std::pair<const Constant *, int64_t> CstExprResTy;
/// ELFWriter - This class implements the common target-independent code for
/// writing ELF files. Targets should derive a class from this to
@ -251,7 +252,7 @@ namespace llvm {
ELFSection &GblS);
void EmitGlobalConstantLargeInt(const ConstantInt *CI, ELFSection &S);
void EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size,
ELFSection &GblS, uint64_t Offset = 0);
ELFSection &GblS, int64_t Offset = 0);
bool EmitSpecialLLVMGlobal(const GlobalVariable *GV);
void EmitXXStructorList(Constant *List, ELFSection &Xtor);
void EmitRelocations();
@ -265,6 +266,7 @@ namespace llvm {
void RelocateField(BinaryObject &BO, uint32_t Offset, int64_t Value,
unsigned Size);
unsigned SortSymbols();
CstExprResTy ResolveConstantExpr(const Constant *CV);
};
}