forked from OSchip/llvm-project
MIR Serialization: Serialize the frame information's stack protector index.
llvm-svn: 245372
This commit is contained in:
parent
913f776ff9
commit
a314d81328
|
@ -337,7 +337,8 @@ struct MachineFrameInfo {
|
|||
unsigned MaxAlignment = 0;
|
||||
bool AdjustsStack = false;
|
||||
bool HasCalls = false;
|
||||
// TODO: Serialize StackProtectorIdx and FunctionContextIdx
|
||||
StringValue StackProtector;
|
||||
// TODO: Serialize FunctionContextIdx
|
||||
unsigned MaxCallFrameSize = 0;
|
||||
bool HasOpaqueSPAdjustment = false;
|
||||
bool HasVAStart = false;
|
||||
|
@ -357,6 +358,8 @@ template <> struct MappingTraits<MachineFrameInfo> {
|
|||
YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment);
|
||||
YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack);
|
||||
YamlIO.mapOptional("hasCalls", MFI.HasCalls);
|
||||
YamlIO.mapOptional("stackProtector", MFI.StackProtector,
|
||||
StringValue()); // Don't print it out when it's empty.
|
||||
YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize);
|
||||
YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment);
|
||||
YamlIO.mapOptional("hasVAStart", MFI.HasVAStart);
|
||||
|
|
|
@ -288,6 +288,7 @@ public:
|
|||
/// Return the index for the stack protector object.
|
||||
int getStackProtectorIndex() const { return StackProtectorIdx; }
|
||||
void setStackProtectorIndex(int I) { StackProtectorIdx = I; }
|
||||
bool hasStackProtectorIndex() const { return StackProtectorIdx != -1; }
|
||||
|
||||
/// Return the index for the function context object.
|
||||
/// This object is used for SjLj exceptions.
|
||||
|
|
|
@ -97,6 +97,7 @@ public:
|
|||
bool parseStandaloneMBB(MachineBasicBlock *&MBB);
|
||||
bool parseStandaloneNamedRegister(unsigned &Reg);
|
||||
bool parseStandaloneVirtualRegister(unsigned &Reg);
|
||||
bool parseStandaloneStackObject(int &FI);
|
||||
|
||||
bool
|
||||
parseBasicBlockDefinition(DenseMap<unsigned, MachineBasicBlock *> &MBBSlots);
|
||||
|
@ -655,6 +656,17 @@ bool MIParser::parseStandaloneVirtualRegister(unsigned &Reg) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseStandaloneStackObject(int &FI) {
|
||||
lex();
|
||||
if (Token.isNot(MIToken::StackObject))
|
||||
return error("expected a stack object");
|
||||
if (parseStackFrameIndex(FI))
|
||||
return true;
|
||||
if (Token.isNot(MIToken::Eof))
|
||||
return error("expected end of string after the stack object reference");
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char *printImplicitRegisterFlag(const MachineOperand &MO) {
|
||||
assert(MO.isImplicit());
|
||||
return MO.isDef() ? "implicit-def" : "implicit";
|
||||
|
@ -1794,3 +1806,12 @@ bool llvm::parseVirtualRegisterReference(unsigned &Reg, SourceMgr &SM,
|
|||
return MIParser(SM, MF, Error, Src, PFS, IRSlots)
|
||||
.parseStandaloneVirtualRegister(Reg);
|
||||
}
|
||||
|
||||
bool llvm::parseStackObjectReference(int &FI, SourceMgr &SM,
|
||||
MachineFunction &MF, StringRef Src,
|
||||
const PerFunctionMIParsingState &PFS,
|
||||
const SlotMapping &IRSlots,
|
||||
SMDiagnostic &Error) {
|
||||
return MIParser(SM, MF, Error, Src, PFS, IRSlots)
|
||||
.parseStandaloneStackObject(FI);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,11 @@ bool parseVirtualRegisterReference(unsigned &Reg, SourceMgr &SM,
|
|||
const SlotMapping &IRSlots,
|
||||
SMDiagnostic &Error);
|
||||
|
||||
bool parseStackObjectReference(int &FI, SourceMgr &SM, MachineFunction &MF,
|
||||
StringRef Src,
|
||||
const PerFunctionMIParsingState &PFS,
|
||||
const SlotMapping &IRSlots, SMDiagnostic &Error);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -493,6 +493,17 @@ bool MIRParserImpl::initializeFrameInfo(MachineFunction &MF,
|
|||
MFI.setCalleeSavedInfo(CSIInfo);
|
||||
if (!CSIInfo.empty())
|
||||
MFI.setCalleeSavedInfoValid(true);
|
||||
|
||||
// Initialize the various stack object references after initializing the
|
||||
// stack objects.
|
||||
if (!YamlMFI.StackProtector.Value.empty()) {
|
||||
SMDiagnostic Error;
|
||||
int FI;
|
||||
if (parseStackObjectReference(FI, SM, MF, YamlMFI.StackProtector.Value, PFS,
|
||||
IRSlots, Error))
|
||||
return error(Error, YamlMFI.StackProtector.SourceRange);
|
||||
MFI.setStackProtectorIndex(FI);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
|
||||
const MachineJumpTableInfo &JTI);
|
||||
void convertStackObjects(yaml::MachineFunction &MF,
|
||||
const MachineFrameInfo &MFI,
|
||||
const MachineFrameInfo &MFI, ModuleSlotTracker &MST,
|
||||
const TargetRegisterInfo *TRI);
|
||||
|
||||
private:
|
||||
|
@ -171,7 +171,7 @@ void MIRPrinter::print(const MachineFunction &MF) {
|
|||
ModuleSlotTracker MST(MF.getFunction()->getParent());
|
||||
MST.incorporateFunction(*MF.getFunction());
|
||||
convert(MST, YamlMF.FrameInfo, *MF.getFrameInfo());
|
||||
convertStackObjects(YamlMF, *MF.getFrameInfo(),
|
||||
convertStackObjects(YamlMF, *MF.getFrameInfo(), MST,
|
||||
MF.getSubtarget().getRegisterInfo());
|
||||
if (const auto *ConstantPool = MF.getConstantPool())
|
||||
convert(YamlMF, *ConstantPool);
|
||||
|
@ -265,6 +265,7 @@ void MIRPrinter::convert(ModuleSlotTracker &MST,
|
|||
|
||||
void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
|
||||
const MachineFrameInfo &MFI,
|
||||
ModuleSlotTracker &MST,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
// Process fixed stack objects.
|
||||
unsigned ID = 0;
|
||||
|
@ -333,6 +334,14 @@ void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
|
|||
assert(!StackObject.IsFixed && "Expected a locally mapped stack object");
|
||||
MF.StackObjects[StackObject.ID].LocalOffset = LocalObject.second;
|
||||
}
|
||||
|
||||
// Print the stack object references in the frame information class after
|
||||
// converting the stack objects.
|
||||
if (MFI.hasStackProtectorIndex()) {
|
||||
raw_string_ostream StrOS(MF.FrameInfo.StackProtector.Value);
|
||||
MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
|
||||
.printStackObjectReference(MFI.getStackProtectorIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void MIRPrinter::convert(yaml::MachineFunction &MF,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
|
||||
--- |
|
||||
@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
|
||||
@__stack_chk_guard = external global i8*
|
||||
|
||||
define i32 @test() #0 {
|
||||
entry:
|
||||
%StackGuardSlot = alloca i8*
|
||||
%StackGuard = load i8*, i8** @__stack_chk_guard
|
||||
call void @llvm.stackprotector(i8* %StackGuard, i8** %StackGuardSlot)
|
||||
%test = alloca i8*, align 8
|
||||
%a = alloca i8, i64 5
|
||||
store i8* %a, i8** %test, align 8
|
||||
%b = load i8*, i8** %test, align 8
|
||||
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %b)
|
||||
call void @llvm.stackprotectorcheck(i8** @__stack_chk_guard)
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
|
||||
declare void @llvm.stackprotector(i8*, i8**) #1
|
||||
|
||||
declare void @llvm.stackprotectorcheck(i8**) #2
|
||||
|
||||
attributes #0 = { ssp "stack-protector-buffer-size"="5" }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind argmemonly }
|
||||
...
|
||||
---
|
||||
name: test
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
stackSize: 40
|
||||
maxAlignment: 8
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
# CHECK: [[@LINE+1]]:21: expected a stack object
|
||||
stackProtector: '0'
|
||||
fixedStack:
|
||||
- { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16,
|
||||
callee-saved-register: '%rbx' }
|
||||
stack:
|
||||
- { id: 0, name: StackGuardSlot, offset: -24, size: 8, alignment: 8 }
|
||||
- { id: 1, name: test, offset: -40, size: 8, alignment: 8 }
|
||||
- { id: 2, name: a, offset: -29, size: 5, alignment: 1 }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: %rbx, %rbx
|
||||
|
||||
frame-setup PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp
|
||||
%rsp = frame-setup SUB64ri8 %rsp, 32, implicit-def dead %eflags
|
||||
%rbx = LOAD_STACK_GUARD :: (invariant load 8 from %ir.__stack_chk_guard)
|
||||
MOV64mr %rsp, 1, _, 24, _, %rbx
|
||||
%rsi = LEA64r %rsp, 1, _, 19, _
|
||||
MOV64mr %rsp, 1, _, 8, _, %rsi
|
||||
%rdi = LEA64r %rip, 1, _, @.str, _
|
||||
dead %eax = MOV32r0 implicit-def dead %eflags, implicit-def %al
|
||||
CALL64pcrel32 @printf, csr_64, implicit %rsp, implicit %rdi, implicit %rsi, implicit %al, implicit-def %rsp, implicit-def %eax
|
||||
CMP64rm killed %rbx, %rsp, 1, _, 24, _, implicit-def %eflags
|
||||
%rsp = ADD64ri8 %rsp, 32, implicit-def dead %eflags
|
||||
%rbx = POP64r implicit-def %rsp, implicit %rsp
|
||||
RETQ %eax
|
||||
...
|
|
@ -0,0 +1,79 @@
|
|||
# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
|
||||
# This test ensures that the MIR parser parses the stack protector stack
|
||||
# object reference in the machine frame info correctly.
|
||||
|
||||
--- |
|
||||
@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
|
||||
@__stack_chk_guard = external global i8*
|
||||
|
||||
define i32 @test() #0 {
|
||||
entry:
|
||||
%StackGuardSlot = alloca i8*
|
||||
%StackGuard = load i8*, i8** @__stack_chk_guard
|
||||
call void @llvm.stackprotector(i8* %StackGuard, i8** %StackGuardSlot)
|
||||
%test = alloca i8*, align 8
|
||||
%a = alloca i8, i64 5
|
||||
store i8* %a, i8** %test, align 8
|
||||
%b = load i8*, i8** %test, align 8
|
||||
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %b)
|
||||
call void @llvm.stackprotectorcheck(i8** @__stack_chk_guard)
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
|
||||
declare void @llvm.stackprotector(i8*, i8**) #1
|
||||
|
||||
declare void @llvm.stackprotectorcheck(i8**) #2
|
||||
|
||||
attributes #0 = { ssp "stack-protector-buffer-size"="5" }
|
||||
attributes #1 = { nounwind }
|
||||
attributes #2 = { nounwind argmemonly }
|
||||
...
|
||||
---
|
||||
name: test
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
stackSize: 40
|
||||
maxAlignment: 8
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
# CHECK-LABEL: name: test
|
||||
# CHECK: frameInfo
|
||||
# CHECK: stackProtector: '%stack.0.StackGuardSlot'
|
||||
stackProtector: '%stack.0.StackGuardSlot'
|
||||
fixedStack:
|
||||
- { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16,
|
||||
callee-saved-register: '%rbx' }
|
||||
stack:
|
||||
- { id: 0, name: StackGuardSlot, offset: -24, size: 8, alignment: 8 }
|
||||
- { id: 1, name: test, offset: -40, size: 8, alignment: 8 }
|
||||
- { id: 2, name: a, offset: -29, size: 5, alignment: 1 }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
successors: %bb.1.entry, %bb.2.entry
|
||||
liveins: %rbx, %rbx
|
||||
|
||||
frame-setup PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp
|
||||
%rsp = frame-setup SUB64ri8 %rsp, 32, implicit-def dead %eflags
|
||||
%rbx = LOAD_STACK_GUARD :: (invariant load 8 from %ir.__stack_chk_guard)
|
||||
MOV64mr %rsp, 1, _, 24, _, %rbx
|
||||
%rsi = LEA64r %rsp, 1, _, 19, _
|
||||
MOV64mr %rsp, 1, _, 8, _, %rsi
|
||||
%rdi = LEA64r %rip, 1, _, @.str, _
|
||||
dead %eax = MOV32r0 implicit-def dead %eflags, implicit-def %al
|
||||
CALL64pcrel32 @printf, csr_64, implicit %rsp, implicit %rdi, implicit %rsi, implicit %al, implicit-def %rsp, implicit-def %eax
|
||||
CMP64rm killed %rbx, %rsp, 1, _, 24, _, implicit-def %eflags
|
||||
JNE_1 %bb.2.entry, implicit %eflags
|
||||
|
||||
bb.1.entry:
|
||||
liveins: %eax
|
||||
|
||||
%rsp = ADD64ri8 %rsp, 32, implicit-def dead %eflags
|
||||
%rbx = POP64r implicit-def %rsp, implicit %rsp
|
||||
RETQ %eax
|
||||
|
||||
bb.2.entry:
|
||||
CALL64pcrel32 $__stack_chk_fail, csr_64, implicit %rsp, implicit-def %rsp
|
||||
...
|
Loading…
Reference in New Issue