[asan] Generate asm instrumentation in MC.

Generate entire ASan asm instrumentation in MC without
relying on runtime helper functions.

Patch by Yuri Gorshenin.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212455 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evgeniy Stepanov 2014-07-07 13:57:37 +00:00
parent e3bf8ea879
commit 5ba71b01d8
6 changed files with 403 additions and 159 deletions

View File

@ -37,8 +37,8 @@ bool IsStackReg(unsigned Reg) {
}
std::string FuncName(unsigned AccessSize, bool IsWrite) {
return std::string("__sanitizer_sanitize_") + (IsWrite ? "store" : "load") +
(utostr(AccessSize));
return std::string("__asan_report_") + (IsWrite ? "store" : "load") +
utostr(AccessSize);
}
class X86AddressSanitizer : public X86AsmInstrumentation {
@ -47,17 +47,19 @@ public:
virtual ~X86AddressSanitizer() {}
// X86AsmInstrumentation implementation:
virtual void InstrumentInstruction(const MCInst &Inst,
OperandVector &Operands, MCContext &Ctx,
const MCInstrInfo &MII,
MCStreamer &Out) override {
virtual void InstrumentInstruction(
const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
const MCInstrInfo &MII, MCStreamer &Out) override {
InstrumentMOV(Inst, Operands, Ctx, MII, Out);
}
// Should be implemented differently in x86_32 and x86_64 subclasses.
virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) = 0;
virtual void InstrumentMemOperandSmallImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) = 0;
virtual void InstrumentMemOperandLargeImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) = 0;
void InstrumentMemOperand(MCParsedAsmOperand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx, MCStreamer &Out);
@ -67,14 +69,15 @@ public:
Out.EmitInstruction(Inst, STI);
}
void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
protected:
const MCSubtargetInfo &STI;
};
void X86AddressSanitizer::InstrumentMemOperand(MCParsedAsmOperand &Op,
unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
void X86AddressSanitizer::InstrumentMemOperand(
MCParsedAsmOperand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
assert(Op.isMem() && "Op should be a memory operand.");
assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
"AccessSize should be a power of two, less or equal than 16.");
@ -84,13 +87,16 @@ void X86AddressSanitizer::InstrumentMemOperand(MCParsedAsmOperand &Op,
if (IsStackReg(MemOp.getMemBaseReg()) || IsStackReg(MemOp.getMemIndexReg()))
return;
InstrumentMemOperandImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
// FIXME: take into account load/store alignment.
if (AccessSize < 8)
InstrumentMemOperandSmallImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
else
InstrumentMemOperandLargeImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
}
void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
OperandVector &Operands, MCContext &Ctx,
const MCInstrInfo &MII,
MCStreamer &Out) {
void X86AddressSanitizer::InstrumentMOV(
const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
const MCInstrInfo &MII, MCStreamer &Out) {
// Access size in bytes.
unsigned AccessSize = 0;
@ -136,22 +142,46 @@ void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
class X86AddressSanitizer32 : public X86AddressSanitizer {
public:
static const long kShadowOffset = 0x20000000;
X86AddressSanitizer32(const MCSubtargetInfo &STI)
: X86AddressSanitizer(STI) {}
virtual ~X86AddressSanitizer32() {}
virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
virtual void InstrumentMemOperandSmallImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
virtual void InstrumentMemOperandLargeImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
private:
void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize,
bool IsWrite, unsigned AddressReg) {
EmitInstruction(Out, MCInstBuilder(X86::CLD));
EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::ESP)
.addReg(X86::ESP).addImm(-16));
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(AddressReg));
const std::string& Fn = FuncName(AccessSize, IsWrite);
MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
const MCSymbolRefExpr *FnExpr =
MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
}
};
void X86AddressSanitizer32::InstrumentMemOperandImpl(X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
MCContext &Ctx,
MCStreamer &Out) {
// FIXME: emit .cfi directives for correct stack unwinding.
void X86AddressSanitizer32::InstrumentMemOperandSmallImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX));
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EDX));
EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
{
MCInst Inst;
Inst.setOpcode(X86::LEA32r);
@ -159,50 +189,175 @@ void X86AddressSanitizer32::InstrumentMemOperandImpl(X86Operand &Op,
Op.addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
EmitInstruction(
Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX));
EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX)
.addReg(X86::ECX).addImm(3));
{
const std::string Func = FuncName(AccessSize, IsWrite);
const MCSymbol *FuncSym = Ctx.GetOrCreateSymbol(StringRef(Func));
const MCSymbolRefExpr *FuncExpr =
MCSymbolRefExpr::Create(FuncSym, MCSymbolRefExpr::VK_PLT, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FuncExpr));
MCInst Inst;
Inst.setOpcode(X86::MOV8rm);
Inst.addOperand(MCOperand::CreateReg(X86::CL));
const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
std::unique_ptr<X86Operand> Op(
X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
Op->addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
EmitInstruction(Out,
MCInstBuilder(X86::TEST8rr).addReg(X86::CL).addReg(X86::CL));
MCSymbol *DoneSym = Ctx.CreateTempSymbol();
const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
EmitInstruction(
Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EDX).addReg(X86::EAX));
EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::EDX)
.addReg(X86::EDX).addImm(7));
switch (AccessSize) {
case 1:
break;
case 2: {
MCInst Inst;
Inst.setOpcode(X86::LEA32r);
Inst.addOperand(MCOperand::CreateReg(X86::EDX));
const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
std::unique_ptr<X86Operand> Op(
X86Operand::CreateMem(0, Disp, X86::EDX, 0, 1, SMLoc(), SMLoc()));
Op->addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
break;
}
case 4:
EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::EDX)
.addReg(X86::EDX).addImm(3));
break;
default:
assert(false && "Incorrect access size");
break;
}
EmitInstruction(
Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::ECX).addReg(X86::CL));
EmitInstruction(
Out, MCInstBuilder(X86::CMP32rr).addReg(X86::EDX).addReg(X86::ECX));
EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX);
EmitLabel(Out, DoneSym);
EmitInstruction(Out, MCInstBuilder(X86::POPF32));
EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EDX));
EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX));
EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX));
}
void X86AddressSanitizer32::InstrumentMemOperandLargeImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX));
EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
{
MCInst Inst;
Inst.setOpcode(X86::LEA32r);
Inst.addOperand(MCOperand::CreateReg(X86::EAX));
Op.addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
EmitInstruction(
Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX));
EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX)
.addReg(X86::ECX).addImm(3));
{
MCInst Inst;
switch (AccessSize) {
case 8:
Inst.setOpcode(X86::CMP8mi);
break;
case 16:
Inst.setOpcode(X86::CMP16mi);
break;
default:
assert(false && "Incorrect access size");
break;
}
const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
std::unique_ptr<X86Operand> Op(
X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
Op->addMemOperands(Inst, 5);
Inst.addOperand(MCOperand::CreateImm(0));
EmitInstruction(Out, Inst);
}
MCSymbol *DoneSym = Ctx.CreateTempSymbol();
const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX);
EmitLabel(Out, DoneSym);
EmitInstruction(Out, MCInstBuilder(X86::POPF32));
EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX));
EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX));
}
class X86AddressSanitizer64 : public X86AddressSanitizer {
public:
static const long kShadowOffset = 0x7fff8000;
X86AddressSanitizer64(const MCSubtargetInfo &STI)
: X86AddressSanitizer(STI) {}
virtual ~X86AddressSanitizer64() {}
virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
};
virtual void InstrumentMemOperandSmallImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
virtual void InstrumentMemOperandLargeImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
MCContext &Ctx,
MCStreamer &Out) {
// FIXME: emit .cfi directives for correct stack unwinding.
// Set %rsp below current red zone (128 bytes wide) using LEA instruction to
// preserve flags.
{
private:
void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
MCInst Inst;
Inst.setOpcode(X86::LEA64r);
Inst.addOperand(MCOperand::CreateReg(X86::RSP));
const MCExpr *Disp = MCConstantExpr::Create(-128, Ctx);
const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx);
std::unique_ptr<X86Operand> Op(
X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
Op->addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize,
bool IsWrite) {
EmitInstruction(Out, MCInstBuilder(X86::CLD));
EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::RSP)
.addReg(X86::RSP).addImm(-16));
const std::string& Fn = FuncName(AccessSize, IsWrite);
MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
const MCSymbolRefExpr *FnExpr =
MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
}
};
void X86AddressSanitizer64::InstrumentMemOperandSmallImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
EmitAdjustRSP(Ctx, Out, -128);
EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX));
EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RCX));
EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RDI));
EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
{
MCInst Inst;
Inst.setOpcode(X86::LEA64r);
@ -210,27 +365,119 @@ void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand &Op,
Op.addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
{
const std::string Func = FuncName(AccessSize, IsWrite);
const MCSymbol *FuncSym = Ctx.GetOrCreateSymbol(StringRef(Func));
const MCSymbolRefExpr *FuncExpr =
MCSymbolRefExpr::Create(FuncSym, MCSymbolRefExpr::VK_PLT, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FuncExpr));
}
EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI));
// Restore old %rsp value.
EmitInstruction(
Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RAX).addReg(X86::RDI));
EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX)
.addReg(X86::RAX).addImm(3));
{
MCInst Inst;
Inst.setOpcode(X86::LEA64r);
Inst.addOperand(MCOperand::CreateReg(X86::RSP));
const MCExpr *Disp = MCConstantExpr::Create(128, Ctx);
Inst.setOpcode(X86::MOV8rm);
Inst.addOperand(MCOperand::CreateReg(X86::AL));
const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
std::unique_ptr<X86Operand> Op(
X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc()));
Op->addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
EmitInstruction(Out,
MCInstBuilder(X86::TEST8rr).addReg(X86::AL).addReg(X86::AL));
MCSymbol *DoneSym = Ctx.CreateTempSymbol();
const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
EmitInstruction(
Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EDI));
EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::ECX)
.addReg(X86::ECX).addImm(7));
switch (AccessSize) {
case 1:
break;
case 2: {
MCInst Inst;
Inst.setOpcode(X86::LEA32r);
Inst.addOperand(MCOperand::CreateReg(X86::ECX));
const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
std::unique_ptr<X86Operand> Op(
X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
Op->addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
break;
}
case 4:
EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::ECX)
.addReg(X86::ECX).addImm(3));
break;
default:
assert(false && "Incorrect access size");
break;
}
EmitInstruction(
Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::EAX).addReg(X86::AL));
EmitInstruction(
Out, MCInstBuilder(X86::CMP32rr).addReg(X86::ECX).addReg(X86::EAX));
EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite);
EmitLabel(Out, DoneSym);
EmitInstruction(Out, MCInstBuilder(X86::POPF64));
EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI));
EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RCX));
EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX));
EmitAdjustRSP(Ctx, Out, 128);
}
void X86AddressSanitizer64::InstrumentMemOperandLargeImpl(
X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
EmitAdjustRSP(Ctx, Out, -128);
EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX));
EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
{
MCInst Inst;
Inst.setOpcode(X86::LEA64r);
Inst.addOperand(MCOperand::CreateReg(X86::RAX));
Op.addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX)
.addReg(X86::RAX).addImm(3));
{
MCInst Inst;
switch (AccessSize) {
case 8:
Inst.setOpcode(X86::CMP8mi);
break;
case 16:
Inst.setOpcode(X86::CMP16mi);
break;
default:
assert(false && "Incorrect access size");
break;
}
const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
std::unique_ptr<X86Operand> Op(
X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc()));
Op->addMemOperands(Inst, 5);
Inst.addOperand(MCOperand::CreateImm(0));
EmitInstruction(Out, Inst);
}
MCSymbol *DoneSym = Ctx.CreateTempSymbol();
const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite);
EmitLabel(Out, DoneSym);
EmitInstruction(Out, MCInstBuilder(X86::POPF64));
EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX));
EmitAdjustRSP(Ctx, Out, 128);
}
} // End anonymous namespace
@ -238,11 +485,9 @@ void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand &Op,
X86AsmInstrumentation::X86AsmInstrumentation() {}
X86AsmInstrumentation::~X86AsmInstrumentation() {}
void X86AsmInstrumentation::InstrumentInstruction(const MCInst &Inst,
OperandVector &Operands,
MCContext &Ctx,
const MCInstrInfo &MII,
MCStreamer &Out) {}
void X86AsmInstrumentation::InstrumentInstruction(
const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
const MCInstrInfo &MII, MCStreamer &Out) {}
X86AsmInstrumentation *
CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,

View File

@ -4,16 +4,16 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; CHECK-LABEL: mov_no_attr
; CHECK-NOT: callq __sanitizer_sanitize_load8@PLT
; CHECK-NOT: callq __sanitizer_sanitize_store8@PLT
; CHECK-NOT: callq __asan_report_load@PLT
; CHECK-NOT: callq __asan_report_store@PLT
define void @mov_no_attr(i64* %dst, i64* %src) {
tail call void asm sideeffect "movq ($1), %rax \0A\09movq %rax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i64* %dst, i64* %src)
ret void
}
; CHECK-LABEL: mov_sanitize
; CHECK: callq __sanitizer_sanitize_load8@PLT
; CHECK: callq __sanitizer_sanitize_store8@PLT
; CHECK: callq __asan_report_load8@PLT
; CHECK: callq __asan_report_store8@PLT
define void @mov_sanitize(i64* %dst, i64* %src) sanitize_address {
tail call void asm sideeffect "movq ($1), %rax \0A\09movq %rax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i64* %dst, i64* %src)
ret void

View File

@ -5,18 +5,35 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK-LABEL: mov1b
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rcx
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: pushfq
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_load1@PLT
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: shrq $3, %rax
; CHECK-NEXT: movb 2147450880(%rax), %al
; CHECK-NEXT: testb %al, %al
; CHECK-NEXT: je [[A:.*]]
; CHECK-NEXT: movl %edi, %ecx
; CHECK-NEXT: andl $7, %ecx
; CHECK-NEXT: movsbl %al, %eax
; CHECK-NEXT: cmpl %eax, %ecx
; CHECK-NEXT: jl {{.*}}
; CHECK-NEXT: cld
; CHECK-NEXT: emms
; CHECK-NEXT: andq $-16, %rsp
; CHECK-NEXT: callq __asan_report_load1@PLT
; CHECK-NEXT: [[A]]:
; CHECK-NEXT: popfq
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: popq %rax
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_store1@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: callq __asan_report_store1@PLT
; CHECK: leaq 128(%rsp), %rsp
; CHECK: movb {{.*}}, {{.*}}
define void @mov1b(i8* %dst, i8* %src) #0 {
@ -27,18 +44,14 @@ entry:
; CHECK-LABEL: mov2b
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_load2@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: leal 1(%ecx), %ecx
; CHECK: callq __asan_report_load2@PLT
; CHECK: leaq 128(%rsp), %rsp
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_store2@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: leal 1(%ecx), %ecx
; CHECK: callq __asan_report_store2@PLT
; CHECK: leaq 128(%rsp), %rsp
; CHECK: movw {{.*}}, {{.*}}
define void @mov2b(i16* %dst, i16* %src) #0 {
@ -49,18 +62,14 @@ entry:
; CHECK-LABEL: mov4b
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_load4@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: addl $3, %ecx
; CHECK: callq __asan_report_load4@PLT
; CHECK: leaq 128(%rsp), %rsp
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_store4@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: addl $3, %ecx
; CHECK: callq __asan_report_store4@PLT
; CHECK: leaq 128(%rsp), %rsp
; CHECK: movl {{.*}}, {{.*}}
define void @mov4b(i32* %dst, i32* %src) #0 {
@ -71,17 +80,35 @@ entry:
; CHECK-LABEL: mov8b
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_load8@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushfq
; CHECK-NEXT: leaq {{.*}}, %rax
; CHECK-NEXT: shrq $3, %rax
; CHECK-NEXT: cmpb $0, 2147450880(%rax)
; CHECK-NEXT: je [[A:.*]]
; CHECK-NEXT: cld
; CHECK-NEXT: emms
; CHECK-NEXT: andq $-16, %rsp
; CHECK-NEXT: callq __asan_report_load8@PLT
; CHECK-NEXT: [[A]]:
; CHECK-NEXT: popfq
; CHECK-NEXT: popq %rax
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_store8@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushfq
; CHECK-NEXT: leaq {{.*}}, %rax
; CHECK-NEXT: shrq $3, %rax
; CHECK-NEXT: cmpb $0, 2147450880(%rax)
; CHECK-NEXT: je [[A:.*]]
; CHECK-NEXT: cld
; CHECK-NEXT: emms
; CHECK-NEXT: andq $-16, %rsp
; CHECK-NEXT: callq __asan_report_store8@PLT
; CHECK-NEXT: [[A]]:
; CHECK-NEXT: popfq
; CHECK-NEXT: popq %rax
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: movq {{.*}}, {{.*}}
@ -93,18 +120,14 @@ entry:
; CHECK-LABEL: mov16b
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_load16@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: cmpw $0, 2147450880(%rax)
; CHECK: callq __asan_report_load16@PLT
; CHECK: leaq 128(%rsp), %rsp
; CHECK: leaq -128(%rsp), %rsp
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: leaq {{.*}}, %rdi
; CHECK-NEXT: callq __sanitizer_sanitize_store16@PLT
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: leaq 128(%rsp), %rsp
; CHECK: cmpw $0, 2147450880(%rax)
; CHECK: callq __asan_report_store16@PLT
; CHECK: leaq 128(%rsp), %rsp
; CHECK: movaps {{.*}}, {{.*}}
define void @mov16b(<2 x i64>* %dst, <2 x i64>* %src) #0 {

View File

@ -7,20 +7,14 @@
# CHECK-LABEL: mov1b:
#
# CHECK: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rsi), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_load1@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK: callq __asan_report_load1@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movb (%rsi), %al
#
# CHECK-NEXT: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rdi), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_store1@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK: callq __asan_report_store1@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movb %al, (%rdi)
mov1b: # @mov1b
@ -42,20 +36,14 @@ mov1b: # @mov1b
# CHECK-LABEL: mov16b:
#
# CHECK: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rsi), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_load16@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK: callq __asan_report_load16@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movaps (%rsi), %xmm0
#
# CHECK-NEXT: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rdi), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_store16@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK: callq __asan_report_store16@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movaps %xmm0, (%rdi)
mov16b: # @mov16b

View File

@ -5,8 +5,8 @@
.align 16, 0x90
.type mov1b,@function
# CHECK-LABEL: mov1b
# CHECK-NOT: callq __sanitizer_sanitize_load1@PLT
# CHECK-NOT: callq __sanitizer_sanitize_store1@PLT
# CHECK-NOT: callq __asan_report_load1@PLT
# CHECK-NOT: callq __asan_report_store1@PLT
mov1b: # @mov1b
.cfi_startproc
# BB#0:

View File

@ -7,38 +7,26 @@
# CHECK-LABEL: swap:
#
# CHECK: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rcx), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_load8@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK: callq __asan_report_load8@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movq (%rcx), %rax
#
# CHECK-NEXT: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rdx), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_load8@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK: callq __asan_report_load8@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movq (%rdx), %rbx
#
# CHECK: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rcx), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_store8@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK-NEXT: leaq -128(%rsp), %rsp
# CHECK: callq __asan_report_store8@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movq %rbx, (%rcx)
#
# CHECK-NEXT: leaq -128(%rsp), %rsp
# CHECK-NEXT: pushq %rdi
# CHECK-NEXT: leaq (%rdx), %rdi
# CHECK-NEXT: callq __sanitizer_sanitize_store8@PLT
# CHECK-NEXT: popq %rdi
# CHECK-NEXT: leaq 128(%rsp), %rsp
# CHECK: callq __asan_report_store8@PLT
# CHECK: leaq 128(%rsp), %rsp
#
# CHECK-NEXT: movq %rax, (%rdx)
swap: # @swap