forked from OSchip/llvm-project
ARM: remove special cases for Darwin dynamic-no-pic mode.
These are handled almost identically to static mode (and ELF's global address materialisation), except that a symbol may have "$non_lazy_ptr" appended. This can be handled by passing appropriate flags along with the instruction instead of using entirely separate pseudo-instructions. llvm-svn: 195655
This commit is contained in:
parent
edcf1ff7d1
commit
db962e2c45
|
@ -774,8 +774,10 @@ getModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
|
|||
llvm_unreachable("Invalid ARMCPModifier!");
|
||||
}
|
||||
|
||||
MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV) {
|
||||
MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
|
||||
unsigned char TargetFlags) {
|
||||
bool isIndirect = Subtarget->isTargetDarwin() &&
|
||||
(TargetFlags & ARMII::MO_NONLAZY) &&
|
||||
Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
|
||||
if (!isIndirect)
|
||||
return getSymbol(GV);
|
||||
|
@ -811,7 +813,11 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
|
|||
MCSym = GetBlockAddressSymbol(BA);
|
||||
} else if (ACPV->isGlobalValue()) {
|
||||
const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
|
||||
MCSym = GetARMGVSymbol(GV);
|
||||
|
||||
// On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so
|
||||
// flag the global as MO_NONLAZY.
|
||||
unsigned char TF = Subtarget->isTargetDarwin() ? ARMII::MO_NONLAZY : 0;
|
||||
MCSym = GetARMGVSymbol(GV, TF);
|
||||
} else if (ACPV->isMachineBasicBlock()) {
|
||||
const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
|
||||
MCSym = MBB->getSymbol();
|
||||
|
@ -1239,26 +1245,21 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
|
||||
|
||||
unsigned TF = MI->getOperand(1).getTargetFlags();
|
||||
bool isPIC = TF == ARMII::MO_LO16_NONLAZY_PIC;
|
||||
const GlobalValue *GV = MI->getOperand(1).getGlobal();
|
||||
MCSymbol *GVSym = GetARMGVSymbol(GV);
|
||||
MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
|
||||
const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
|
||||
if (isPIC) {
|
||||
MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
|
||||
getFunctionNumber(),
|
||||
MI->getOperand(2).getImm(), OutContext);
|
||||
const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
|
||||
unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
|
||||
const MCExpr *PCRelExpr =
|
||||
ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr,
|
||||
MCBinaryExpr::CreateAdd(LabelSymExpr,
|
||||
|
||||
MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
|
||||
getFunctionNumber(),
|
||||
MI->getOperand(2).getImm(), OutContext);
|
||||
const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
|
||||
unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
|
||||
const MCExpr *PCRelExpr =
|
||||
ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr,
|
||||
MCBinaryExpr::CreateAdd(LabelSymExpr,
|
||||
MCConstantExpr::Create(PCAdj, OutContext),
|
||||
OutContext), OutContext), OutContext);
|
||||
OutContext), OutContext), OutContext);
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
|
||||
} else {
|
||||
const MCExpr *RefExpr= ARMMCExpr::CreateLower16(GVSymExpr, OutContext);
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(RefExpr));
|
||||
}
|
||||
|
||||
// Add predicate operands.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
|
@ -1277,26 +1278,21 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
|
||||
|
||||
unsigned TF = MI->getOperand(2).getTargetFlags();
|
||||
bool isPIC = TF == ARMII::MO_HI16_NONLAZY_PIC;
|
||||
const GlobalValue *GV = MI->getOperand(2).getGlobal();
|
||||
MCSymbol *GVSym = GetARMGVSymbol(GV);
|
||||
MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
|
||||
const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
|
||||
if (isPIC) {
|
||||
MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
|
||||
getFunctionNumber(),
|
||||
MI->getOperand(3).getImm(), OutContext);
|
||||
const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
|
||||
unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
|
||||
const MCExpr *PCRelExpr =
|
||||
|
||||
MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(),
|
||||
getFunctionNumber(),
|
||||
MI->getOperand(3).getImm(), OutContext);
|
||||
const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
|
||||
unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
|
||||
const MCExpr *PCRelExpr =
|
||||
ARMMCExpr::CreateUpper16(MCBinaryExpr::CreateSub(GVSymExpr,
|
||||
MCBinaryExpr::CreateAdd(LabelSymExpr,
|
||||
MCConstantExpr::Create(PCAdj, OutContext),
|
||||
OutContext), OutContext), OutContext);
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
|
||||
} else {
|
||||
const MCExpr *RefExpr= ARMMCExpr::CreateUpper16(GVSymExpr, OutContext);
|
||||
TmpInst.addOperand(MCOperand::CreateExpr(RefExpr));
|
||||
}
|
||||
// Add predicate operands.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
|
|
|
@ -115,7 +115,7 @@ private:
|
|||
|
||||
MCSymbol *GetARMSJLJEHLabel() const;
|
||||
|
||||
MCSymbol *GetARMGVSymbol(const GlobalValue *GV);
|
||||
MCSymbol *GetARMGVSymbol(const GlobalValue *GV, unsigned char TargetFlags);
|
||||
|
||||
public:
|
||||
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
|
||||
|
|
|
@ -1325,10 +1325,8 @@ bool ARMBaseInstrInfo::produceSameValue(const MachineInstr *MI0,
|
|||
Opcode == ARM::t2LDRpci_pic ||
|
||||
Opcode == ARM::tLDRpci ||
|
||||
Opcode == ARM::tLDRpci_pic ||
|
||||
Opcode == ARM::MOV_ga_dyn ||
|
||||
Opcode == ARM::MOV_ga_pcrel ||
|
||||
Opcode == ARM::MOV_ga_pcrel_ldr ||
|
||||
Opcode == ARM::t2MOV_ga_dyn ||
|
||||
Opcode == ARM::t2MOV_ga_pcrel) {
|
||||
if (MI1->getOpcode() != Opcode)
|
||||
return false;
|
||||
|
@ -1340,10 +1338,8 @@ bool ARMBaseInstrInfo::produceSameValue(const MachineInstr *MI0,
|
|||
if (MO0.getOffset() != MO1.getOffset())
|
||||
return false;
|
||||
|
||||
if (Opcode == ARM::MOV_ga_dyn ||
|
||||
Opcode == ARM::MOV_ga_pcrel ||
|
||||
if (Opcode == ARM::MOV_ga_pcrel ||
|
||||
Opcode == ARM::MOV_ga_pcrel_ldr ||
|
||||
Opcode == ARM::t2MOV_ga_dyn ||
|
||||
Opcode == ARM::t2MOV_ga_pcrel)
|
||||
// Ignore the PC labels.
|
||||
return MO0.getGlobal() == MO1.getGlobal();
|
||||
|
|
|
@ -898,10 +898,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
|
|||
return true;
|
||||
}
|
||||
|
||||
case ARM::MOV_ga_dyn:
|
||||
case ARM::MOV_ga_pcrel:
|
||||
case ARM::MOV_ga_pcrel_ldr:
|
||||
case ARM::t2MOV_ga_dyn:
|
||||
case ARM::t2MOV_ga_pcrel: {
|
||||
// Expand into movw + movw. Also "add pc" / ldr [pc] in PIC mode.
|
||||
unsigned LabelId = AFI->createPICLabelUId();
|
||||
|
@ -910,14 +908,11 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
|
|||
const MachineOperand &MO1 = MI.getOperand(1);
|
||||
const GlobalValue *GV = MO1.getGlobal();
|
||||
unsigned TF = MO1.getTargetFlags();
|
||||
bool isARM = (Opcode != ARM::t2MOV_ga_pcrel && Opcode!=ARM::t2MOV_ga_dyn);
|
||||
bool isPIC = (Opcode != ARM::MOV_ga_dyn && Opcode != ARM::t2MOV_ga_dyn);
|
||||
bool isARM = Opcode != ARM::t2MOV_ga_pcrel;
|
||||
unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel;
|
||||
unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel;
|
||||
unsigned LO16TF = isPIC
|
||||
? ARMII::MO_LO16_NONLAZY_PIC : ARMII::MO_LO16_NONLAZY;
|
||||
unsigned HI16TF = isPIC
|
||||
? ARMII::MO_HI16_NONLAZY_PIC : ARMII::MO_HI16_NONLAZY;
|
||||
unsigned LO16TF = TF | ARMII::MO_LO16;
|
||||
unsigned HI16TF = TF | ARMII::MO_HI16;
|
||||
unsigned PICAddOpc = isARM
|
||||
? (Opcode == ARM::MOV_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)
|
||||
: ARM::tPICADD;
|
||||
|
@ -925,16 +920,11 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
|
|||
TII->get(LO16Opc), DstReg)
|
||||
.addGlobalAddress(GV, MO1.getOffset(), TF | LO16TF)
|
||||
.addImm(LabelId);
|
||||
MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
|
||||
TII->get(HI16Opc), DstReg)
|
||||
|
||||
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc), DstReg)
|
||||
.addReg(DstReg)
|
||||
.addGlobalAddress(GV, MO1.getOffset(), TF | HI16TF)
|
||||
.addImm(LabelId);
|
||||
if (!isPIC) {
|
||||
TransferImpOps(MI, MIB1, MIB2);
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
MachineInstrBuilder MIB3 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
|
||||
TII->get(PICAddOpc))
|
||||
|
|
|
@ -685,19 +685,20 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, MVT VT) {
|
|||
if (Subtarget->useMovt() &&
|
||||
Subtarget->isTargetDarwin() == (RelocM != Reloc::Static)) {
|
||||
unsigned Opc;
|
||||
unsigned char TF = 0;
|
||||
if (Subtarget->isTargetDarwin() && RelocM != Reloc::Static)
|
||||
TF = ARMII::MO_NONLAZY;
|
||||
|
||||
switch (RelocM) {
|
||||
case Reloc::PIC_:
|
||||
Opc = isThumb2 ? ARM::t2MOV_ga_pcrel : ARM::MOV_ga_pcrel;
|
||||
break;
|
||||
case Reloc::DynamicNoPIC:
|
||||
Opc = isThumb2 ? ARM::t2MOV_ga_dyn : ARM::MOV_ga_dyn;
|
||||
break;
|
||||
default:
|
||||
Opc = isThumb2 ? ARM::t2MOVi32imm : ARM::MOVi32imm;
|
||||
break;
|
||||
}
|
||||
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc),
|
||||
DestReg).addGlobalAddress(GV));
|
||||
DestReg).addGlobalAddress(GV, 0, TF));
|
||||
} else {
|
||||
// MachineConstantPool wants an explicit alignment.
|
||||
unsigned Align = TD.getPrefTypeAlignment(GV->getType());
|
||||
|
|
|
@ -1009,7 +1009,6 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||
switch (Opcode) {
|
||||
default: return 0;
|
||||
case ARMISD::Wrapper: return "ARMISD::Wrapper";
|
||||
case ARMISD::WrapperDYN: return "ARMISD::WrapperDYN";
|
||||
case ARMISD::WrapperPIC: return "ARMISD::WrapperPIC";
|
||||
case ARMISD::WrapperJT: return "ARMISD::WrapperJT";
|
||||
case ARMISD::CALL: return "ARMISD::CALL";
|
||||
|
@ -2548,10 +2547,12 @@ SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op,
|
|||
return DAG.getNode(ARMISD::Wrapper, dl, PtrVT,
|
||||
DAG.getTargetGlobalAddress(GV, dl, PtrVT));
|
||||
|
||||
unsigned Wrapper = (RelocM == Reloc::PIC_)
|
||||
? ARMISD::WrapperPIC : ARMISD::WrapperDYN;
|
||||
SDValue Result = DAG.getNode(Wrapper, dl, PtrVT,
|
||||
DAG.getTargetGlobalAddress(GV, dl, PtrVT));
|
||||
unsigned Wrapper =
|
||||
RelocM == Reloc::PIC_ ? ARMISD::WrapperPIC : ARMISD::Wrapper;
|
||||
|
||||
SDValue G = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, ARMII::MO_NONLAZY);
|
||||
SDValue Result = DAG.getNode(Wrapper, dl, PtrVT, G);
|
||||
|
||||
if (Subtarget->GVIsIndirectSymbol(GV, RelocM))
|
||||
Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Result,
|
||||
MachinePointerInfo::getGOT(),
|
||||
|
|
|
@ -35,8 +35,6 @@ namespace llvm {
|
|||
|
||||
Wrapper, // Wrapper - A wrapper node for TargetConstantPool,
|
||||
// TargetExternalSymbol, and TargetGlobalAddress.
|
||||
WrapperDYN, // WrapperDYN - A wrapper node for TargetGlobalAddress in
|
||||
// DYN mode.
|
||||
WrapperPIC, // WrapperPIC - A wrapper node for TargetGlobalAddress in
|
||||
// PIC mode.
|
||||
WrapperJT, // WrapperJT - A wrapper node for TargetJumpTable
|
||||
|
|
|
@ -95,7 +95,6 @@ def ARMSmlal : SDNode<"ARMISD::SMLAL", SDT_ARM64bitmlal>;
|
|||
|
||||
// Node definitions.
|
||||
def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>;
|
||||
def ARMWrapperDYN : SDNode<"ARMISD::WrapperDYN", SDTIntUnaryOp>;
|
||||
def ARMWrapperPIC : SDNode<"ARMISD::WrapperPIC", SDTIntUnaryOp>;
|
||||
def ARMWrapperJT : SDNode<"ARMISD::WrapperJT", SDTIntBinOp>;
|
||||
|
||||
|
@ -5193,11 +5192,6 @@ def MOV_ga_pcrel : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr),
|
|||
[(set GPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>,
|
||||
Requires<[IsARM, UseMovt]>;
|
||||
|
||||
def MOV_ga_dyn : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr),
|
||||
IIC_iMOVix2,
|
||||
[(set GPR:$dst, (ARMWrapperDYN tglobaladdr:$addr))]>,
|
||||
Requires<[IsARM, UseMovt]>;
|
||||
|
||||
let AddedComplexity = 10 in
|
||||
def MOV_ga_pcrel_ldr : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr),
|
||||
IIC_iMOVix2ld,
|
||||
|
|
|
@ -3793,10 +3793,6 @@ def t2MOV_ga_pcrel : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr),
|
|||
[(set rGPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>,
|
||||
Requires<[IsThumb2, UseMovt]>;
|
||||
|
||||
def t2MOV_ga_dyn : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr),
|
||||
IIC_iMOVix2,
|
||||
[(set rGPR:$dst, (ARMWrapperDYN tglobaladdr:$addr))]>,
|
||||
Requires<[IsThumb2, UseMovt]>;
|
||||
}
|
||||
|
||||
// ConstantPool, GlobalAddress, and JumpTable
|
||||
|
|
|
@ -26,11 +26,12 @@ using namespace llvm;
|
|||
MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
|
||||
const MCSymbol *Symbol) {
|
||||
const MCExpr *Expr;
|
||||
switch (MO.getTargetFlags()) {
|
||||
unsigned Option = MO.getTargetFlags() & ARMII::MO_OPTION_MASK;
|
||||
switch (Option) {
|
||||
default: {
|
||||
Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
|
||||
OutContext);
|
||||
switch (MO.getTargetFlags()) {
|
||||
switch (Option) {
|
||||
default: llvm_unreachable("Unknown target flag on symbol operand");
|
||||
case 0:
|
||||
break;
|
||||
|
@ -81,9 +82,11 @@ bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,
|
|||
MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
|
||||
MO.getMBB()->getSymbol(), OutContext));
|
||||
break;
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
MCOp = GetSymbolRef(MO, getSymbol(MO.getGlobal()));
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
MCOp = GetSymbolRef(MO,
|
||||
GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));
|
||||
break;
|
||||
}
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
MCOp = GetSymbolRef(MO,
|
||||
GetExternalSymbolSymbol(MO.getSymbolName()));
|
||||
|
|
|
@ -278,42 +278,36 @@ namespace ARMII {
|
|||
//===------------------------------------------------------------------===//
|
||||
// ARM Specific MachineOperand flags.
|
||||
|
||||
MO_NO_FLAG,
|
||||
MO_NO_FLAG = 0,
|
||||
|
||||
/// MO_LO16 - On a symbol operand, this represents a relocation containing
|
||||
/// lower 16 bit of the address. Used only via movw instruction.
|
||||
MO_LO16,
|
||||
MO_LO16 = 0x1,
|
||||
|
||||
/// MO_HI16 - On a symbol operand, this represents a relocation containing
|
||||
/// higher 16 bit of the address. Used only via movt instruction.
|
||||
MO_HI16,
|
||||
|
||||
/// MO_LO16_NONLAZY - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
|
||||
/// i.e. "FOO$non_lazy_ptr".
|
||||
/// Used only via movw instruction.
|
||||
MO_LO16_NONLAZY,
|
||||
|
||||
/// MO_HI16_NONLAZY - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
|
||||
/// i.e. "FOO$non_lazy_ptr". Used only via movt instruction.
|
||||
MO_HI16_NONLAZY,
|
||||
|
||||
/// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the PC relative address of the
|
||||
/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
|
||||
/// Used only via movw instruction.
|
||||
MO_LO16_NONLAZY_PIC,
|
||||
|
||||
/// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the PC relative address of the
|
||||
/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
|
||||
/// Used only via movt instruction.
|
||||
MO_HI16_NONLAZY_PIC,
|
||||
MO_HI16 = 0x2,
|
||||
|
||||
/// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a
|
||||
/// call operand.
|
||||
MO_PLT
|
||||
MO_PLT = 0x3,
|
||||
|
||||
/// MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects
|
||||
/// just that part of the flag set.
|
||||
MO_OPTION_MASK = 0x7f,
|
||||
|
||||
/// MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it
|
||||
/// represents a symbol which, if indirect, will get special Darwin mangling
|
||||
/// as a non-lazy-ptr indirect symbol (i.e. "L_FOO$non_lazy_ptr"). Can be
|
||||
/// combined with MO_LO16, MO_HI16 or MO_NO_FLAG (in a constant-pool, for
|
||||
/// example).
|
||||
MO_NONLAZY = 0x80,
|
||||
|
||||
// It's undefined behaviour if an enum overflows the range between its
|
||||
// smallest and largest values, but since these are |ed together, it can
|
||||
// happen. Put a sentinel in (values of this enum are stored as "unsigned
|
||||
// char").
|
||||
MO_UNUSED_MAXIMUM = 0xff
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
Loading…
Reference in New Issue