mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
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:
parent
e8af1f9afe
commit
64a6b39417
@ -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());
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user