| Index: src/IceTargetLoweringX8632.cpp
|
| diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
|
| index d36ad1695191b49e77d7ad516c33d80eacfbf890..eb6afca1ecc552807b41855d43a902b92cdde4e6 100644
|
| --- a/src/IceTargetLoweringX8632.cpp
|
| +++ b/src/IceTargetLoweringX8632.cpp
|
| @@ -136,6 +136,8 @@ const uint32_t X86_LOG2_OF_MIN_STACK_SLOT_SIZE = 2;
|
| const uint32_t X86_LOG2_OF_MAX_STACK_SLOT_SIZE = 4;
|
| // The number of different NOP instructions
|
| const uint32_t X86_NUM_NOP_VARIANTS = 5;
|
| +// Randomize integer immediates at least 2 bytes in size.
|
| +const uint64_t X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD = 0xffff;
|
|
|
| // Value and Alignment are in bytes. Return Value adjusted to the next
|
| // highest multiple of Alignment.
|
| @@ -151,6 +153,17 @@ uint32_t applyStackAlignment(uint32_t Value) {
|
| return applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
|
| }
|
|
|
| +// This gives a name to the immediate so it can be identified as a
|
| +// constant pool entry.
|
| +IceString nameImmediate(Constant *Immediate) {
|
| + bool IsRelocatable = llvm::isa<ConstantRelocatable>(Immediate);
|
| + IceString Name;
|
| + llvm::raw_string_ostream NameBuf(Name);
|
| + NameBuf << (IsRelocatable ? "L$__reloc" : "L$") << Immediate->getType() << "$"
|
| + << Immediate->getPoolEntryID();
|
| + return NameBuf.str();
|
| +}
|
| +
|
| // Instruction set options
|
| namespace cl = ::llvm::cl;
|
| cl::opt<TargetX8632::X86InstructionSet> CLInstructionSet(
|
| @@ -162,6 +175,51 @@ cl::opt<TargetX8632::X86InstructionSet> CLInstructionSet(
|
| clEnumValN(TargetX8632::SSE4_1, "sse4.1",
|
| "Enable SSE 4.1 instructions"), clEnumValEnd));
|
|
|
| +enum RandomizeImmediates {
|
| + Randomize_None,
|
| + Randomize_ConstantBlinding,
|
| + Randomize_ConstantPooling
|
| +};
|
| +
|
| +cl::opt<RandomizeImmediates> CLRandomizeImmediates(
|
| + "randomize-immediates",
|
| + cl::desc("Randomize the representation of immediates"),
|
| + cl::init(Randomize_None),
|
| + cl::values(clEnumValN(Randomize_None, "none", "Don't randomize (default)"),
|
| + clEnumValN(Randomize_ConstantBlinding, "constant-blinding",
|
| + "Use constant blinding"),
|
| + clEnumValN(Randomize_ConstantPooling, "constant-pooling",
|
| + "Use constant pooling"),
|
| + clEnumValEnd));
|
| +
|
| +bool immediateShouldBeRandomized(Operand *Immediate) {
|
| + if (!CLRandomizeImmediates)
|
| + return false;
|
| + if (ConstantInteger *ConstInt =
|
| + llvm::dyn_cast_or_null<ConstantInteger>(Immediate)) {
|
| + // i64 should have been split at this point.
|
| + assert(ConstInt->getType() != IceType_i64);
|
| + return ConstInt->getType() == IceType_i32 &&
|
| + (ConstInt->getValue() +
|
| + X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD / 2) >=
|
| + X86_INT_IMMEDIATE_RANDOMIZATION_THRESHOLD;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +// Return a string representation of the type that is suitable for use
|
| +// in an identifier.
|
| +IceString typeIdentString(const Type Ty) {
|
| + IceString Str;
|
| + llvm::raw_string_ostream BaseOS(Str);
|
| + if (isVectorType(Ty)) {
|
| + BaseOS << "v" << typeNumElements(Ty) << typeElementType(Ty);
|
| + } else {
|
| + BaseOS << Ty;
|
| + }
|
| + return BaseOS.str();
|
| +}
|
| +
|
| // In some cases, there are x-macros tables for both high-level and
|
| // low-level instructions/operands that use the same enum key value.
|
| // The tables are kept separate to maintain a proper separation
|
| @@ -263,7 +321,8 @@ TargetX8632::TargetX8632(Cfg *Func)
|
| : TargetLowering(Func), InstructionSet(CLInstructionSet),
|
| IsEbpBasedFrame(false), NeedsStackAlignment(false), FrameSizeLocals(0),
|
| SpillAreaSizeBytes(0), NextLabelNumber(0), ComputedLiveRanges(false),
|
| - PhysicalRegisters(VarList(Reg_NUM)) {
|
| + PhysicalRegisters(VarList(Reg_NUM)),
|
| + ConstantBlindingCookieInitialized(false), ConstantBlindingCookie(0) {
|
| // TODO: Don't initialize IntegerRegisters and friends every time.
|
| // Instead, initialize in some sort of static initializer for the
|
| // class.
|
| @@ -983,9 +1042,41 @@ template <typename T> void TargetX8632::emitConstantPool() const {
|
| }
|
| }
|
|
|
| +void TargetX8632::emitPooledImmediates() const {
|
| + Ostream &Str = Ctx->getStrEmit();
|
| + SizeT Align = typeWidthInBytesOnStack(IceType_i32);
|
| + // TODO: Determine the right directives to place here.
|
| + Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
|
| + << "\n";
|
| + Str << "\t.align\t" << Align << "\n";
|
| + ConstantList PooledImmediates = Ctx->getImmediatePool();
|
| + for (ConstantList::const_iterator I = PooledImmediates.begin(),
|
| + E = PooledImmediates.end();
|
| + I != E; ++I) {
|
| + Constant *Value = *I;
|
| + IceString Name = nameImmediate(Value);
|
| + Str << Name << ":\n";
|
| + if (ConstantInteger *Int = llvm::dyn_cast<ConstantInteger>(Value)) {
|
| + assert(Int->getType() == IceType_i32);
|
| + char buf[30];
|
| + int CharsPrinted = snprintf(buf, llvm::array_lengthof(buf), "0x%x",
|
| + (uint32_t)Int->getValue());
|
| + assert(CharsPrinted >= 0 &&
|
| + (size_t)CharsPrinted < llvm::array_lengthof(buf));
|
| + Str << "\t.long\t" << buf << "\n";
|
| + } else if (ConstantRelocatable *Reloc =
|
| + llvm::dyn_cast<ConstantRelocatable>(Value)) {
|
| + Str << "\t.long\t";
|
| + Reloc->emit(Ctx);
|
| + Str << "\n";
|
| + }
|
| + }
|
| +}
|
| +
|
| void TargetX8632::emitConstants() const {
|
| emitConstantPool<PoolTypeConverter<float> >();
|
| emitConstantPool<PoolTypeConverter<double> >();
|
| + emitPooledImmediates();
|
|
|
| // No need to emit constants from the int pool since (for x86) they
|
| // are embedded as immediates in the instructions.
|
| @@ -3808,8 +3899,9 @@ void TargetX8632::lowerSelect(const InstSelect *Inst) {
|
| _mov(DestLo, SrcLoRI);
|
| _mov(DestHi, SrcHiRI);
|
| } else {
|
| - _cmp(ConditionRMI, Zero);
|
| + // Call legalize() before _cmp, since legalize() may modify flags.
|
| SrcT = legalize(SrcT, Legal_Reg | Legal_Imm, true);
|
| + _cmp(ConditionRMI, Zero);
|
| _mov(Dest, SrcT);
|
| _br(InstX8632Br::Br_ne, Label);
|
| Context.insert(InstFakeUse::create(Func, Dest));
|
| @@ -4027,6 +4119,49 @@ Variable *TargetX8632::copyToReg(Operand *Src, int32_t RegNum) {
|
| return Reg;
|
| }
|
|
|
| +// Insert code to randomize the representation of the immediate. Return
|
| +// a register that holds the (derandomized) value of the immediate.
|
| +// WARNING: Constant blinding overwrites the flags register.
|
| +Variable *TargetX8632::randomizeImmediate(Constant *Immediate) {
|
| + assert(llvm::isa<ConstantInteger>(Immediate) ||
|
| + llvm::isa<ConstantRelocatable>(Immediate));
|
| +
|
| + if (CLRandomizeImmediates == Randomize_None)
|
| + return legalizeToVar(Immediate);
|
| +
|
| + Variable *Dest = makeReg(Immediate->getType());
|
| +
|
| + if (CLRandomizeImmediates == Randomize_ConstantPooling) {
|
| + const Type Ty = Immediate->getType();
|
| + const int64_t Offset = 0;
|
| + const IceString Name = nameImmediate(Immediate);
|
| + const bool SuppressMangling = true;
|
| + Ctx->addConstantPooledImmediate(Name, Immediate);
|
| + Constant *Sym = Ctx->getConstantSym(Ty, Offset, Name, SuppressMangling);
|
| + // LEAHACK: Once a proper assembler is used, change this to be
|
| + // mov Dest, [Sym].
|
| + _mov(Dest, OperandX8632Mem::create(Func, Ty, NULL, Sym));
|
| + } else {
|
| + assert(CLRandomizeImmediates == Randomize_ConstantBlinding);
|
| + // Mask integer immediates with a random XOR key.
|
| + ConstantInteger *IntegerImmediate = llvm::cast<ConstantInteger>(Immediate);
|
| + assert(IntegerImmediate->getType() != IceType_i64);
|
| + uint64_t Value = IntegerImmediate->getValue();
|
| + if (!ConstantBlindingCookieInitialized) {
|
| + RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
|
| + ConstantBlindingCookie =
|
| + RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1);
|
| + ConstantBlindingCookieInitialized = true;
|
| + }
|
| + uint32_t Mask1 = ConstantBlindingCookie;
|
| + uint32_t Mask2 = Mask1 ^ Value;
|
| + _mov(Dest, Ctx->getConstantInt(IceType_i32, Mask1));
|
| + _xor(Dest, Ctx->getConstantInt(IceType_i32, Mask2));
|
| + }
|
| +
|
| + return Dest;
|
| +}
|
| +
|
| Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| bool AllowOverlap, int32_t RegNum) {
|
| // Assert that a physical register is allowed. To date, all calls
|
| @@ -4044,6 +4179,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| // that the Base and Index components are in physical registers.
|
| Variable *Base = Mem->getBase();
|
| Variable *Index = Mem->getIndex();
|
| + Constant *Offset = Mem->getOffset();
|
| Variable *RegBase = NULL;
|
| Variable *RegIndex = NULL;
|
| if (Base) {
|
| @@ -4052,10 +4188,22 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| if (Index) {
|
| RegIndex = legalizeToVar(Index, true);
|
| }
|
| +
|
| + if (immediateShouldBeRandomized(Offset)) {
|
| + // lea new_base [base + randomize(offset)]
|
| + Variable *RegOffset = randomizeImmediate(Offset);
|
| + OperandX8632Mem *NewBaseAddr = OperandX8632Mem::create(
|
| + Func, Mem->getType(), RegBase, NULL, RegOffset, 0);
|
| + Variable *NewBase = makeReg(IceType_i32);
|
| + _lea(NewBase, NewBaseAddr);
|
| + RegBase = NewBase;
|
| + Offset = NULL;
|
| + }
|
| +
|
| if (Base != RegBase || Index != RegIndex) {
|
| - From = OperandX8632Mem::create(
|
| - Func, Mem->getType(), RegBase, Mem->getOffset(), RegIndex,
|
| - Mem->getShift(), Mem->getSegmentRegister());
|
| + From = OperandX8632Mem::create(Func, Mem->getType(), RegBase, Offset,
|
| + RegIndex, Mem->getShift(),
|
| + Mem->getSegmentRegister());
|
| }
|
|
|
| if (!(Allowed & Legal_Mem)) {
|
| @@ -4082,6 +4230,11 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| }
|
| // There should be no constants of vector type (other than undef).
|
| assert(!isVectorType(From->getType()));
|
| +
|
| + if (immediateShouldBeRandomized(From)) {
|
| + return randomizeImmediate(llvm::cast<Constant>(From));
|
| + }
|
| +
|
| bool NeedsReg = false;
|
| if (!(Allowed & Legal_Imm))
|
| // Immediate specifically not allowed
|
|
|