mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-24 21:25:41 +00:00
MIR Serialization: Serialize MMI's variable debug information.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245396 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0f33e74711
commit
a80c044041
@ -196,6 +196,9 @@ struct MachineStackObject {
|
||||
unsigned Alignment = 0;
|
||||
StringValue CalleeSavedRegister;
|
||||
Optional<int64_t> LocalOffset;
|
||||
StringValue DebugVar;
|
||||
StringValue DebugExpr;
|
||||
StringValue DebugLoc;
|
||||
};
|
||||
|
||||
template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
|
||||
@ -221,6 +224,12 @@ template <> struct MappingTraits<MachineStackObject> {
|
||||
YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
|
||||
StringValue()); // Don't print it out when it's empty.
|
||||
YamlIO.mapOptional("local-offset", Object.LocalOffset);
|
||||
YamlIO.mapOptional("di-variable", Object.DebugVar,
|
||||
StringValue()); // Don't print it out when it's empty.
|
||||
YamlIO.mapOptional("di-expression", Object.DebugExpr,
|
||||
StringValue()); // Don't print it out when it's empty.
|
||||
YamlIO.mapOptional("di-location", Object.DebugLoc,
|
||||
StringValue()); // Don't print it out when it's empty.
|
||||
}
|
||||
|
||||
static const bool flow = true;
|
||||
|
@ -100,6 +100,7 @@ public:
|
||||
bool parseStandaloneNamedRegister(unsigned &Reg);
|
||||
bool parseStandaloneVirtualRegister(unsigned &Reg);
|
||||
bool parseStandaloneStackObject(int &FI);
|
||||
bool parseStandaloneMDNode(MDNode *&Node);
|
||||
|
||||
bool
|
||||
parseBasicBlockDefinition(DenseMap<unsigned, MachineBasicBlock *> &MBBSlots);
|
||||
@ -677,6 +678,17 @@ bool MIParser::parseStandaloneStackObject(int &FI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseStandaloneMDNode(MDNode *&Node) {
|
||||
lex();
|
||||
if (Token.isNot(MIToken::exclaim))
|
||||
return error("expected a metadata node");
|
||||
if (parseMDNode(Node))
|
||||
return true;
|
||||
if (Token.isNot(MIToken::Eof))
|
||||
return error("expected end of string after the metadata node");
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char *printImplicitRegisterFlag(const MachineOperand &MO) {
|
||||
assert(MO.isImplicit());
|
||||
return MO.isDef() ? "implicit-def" : "implicit";
|
||||
@ -1858,3 +1870,9 @@ bool llvm::parseStackObjectReference(int &FI, SourceMgr &SM,
|
||||
return MIParser(SM, MF, Error, Src, PFS, IRSlots)
|
||||
.parseStandaloneStackObject(FI);
|
||||
}
|
||||
|
||||
bool llvm::parseMDNode(MDNode *&Node, SourceMgr &SM, MachineFunction &MF,
|
||||
StringRef Src, const PerFunctionMIParsingState &PFS,
|
||||
const SlotMapping &IRSlots, SMDiagnostic &Error) {
|
||||
return MIParser(SM, MF, Error, Src, PFS, IRSlots).parseStandaloneMDNode(Node);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ class BasicBlock;
|
||||
class MachineBasicBlock;
|
||||
class MachineInstr;
|
||||
class MachineFunction;
|
||||
class MDNode;
|
||||
struct SlotMapping;
|
||||
class SMDiagnostic;
|
||||
class SourceMgr;
|
||||
@ -89,6 +90,10 @@ bool parseStackObjectReference(int &FI, SourceMgr &SM, MachineFunction &MF,
|
||||
const PerFunctionMIParsingState &PFS,
|
||||
const SlotMapping &IRSlots, SMDiagnostic &Error);
|
||||
|
||||
bool parseMDNode(MDNode *&Node, SourceMgr &SM, MachineFunction &MF,
|
||||
StringRef Src, const PerFunctionMIParsingState &PFS,
|
||||
const SlotMapping &IRSlots, SMDiagnostic &Error);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/MIRYamlMapping.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
@ -113,6 +114,11 @@ public:
|
||||
const yaml::StringValue &RegisterSource,
|
||||
int FrameIdx);
|
||||
|
||||
bool parseStackObjectsDebugInfo(MachineFunction &MF,
|
||||
PerFunctionMIParsingState &PFS,
|
||||
const yaml::MachineStackObject &Object,
|
||||
int FrameIdx);
|
||||
|
||||
bool initializeConstantPool(MachineConstantPool &ConstantPool,
|
||||
const yaml::MachineFunction &YamlMF,
|
||||
const MachineFunction &MF,
|
||||
@ -123,6 +129,9 @@ public:
|
||||
PerFunctionMIParsingState &PFS);
|
||||
|
||||
private:
|
||||
bool parseMDNode(MDNode *&Node, const yaml::StringValue &Source,
|
||||
MachineFunction &MF, const PerFunctionMIParsingState &PFS);
|
||||
|
||||
bool parseMBBReference(MachineBasicBlock *&MBB,
|
||||
const yaml::StringValue &Source, MachineFunction &MF,
|
||||
const PerFunctionMIParsingState &PFS);
|
||||
@ -489,6 +498,8 @@ bool MIRParserImpl::initializeFrameInfo(MachineFunction &MF,
|
||||
return true;
|
||||
if (Object.LocalOffset)
|
||||
MFI.mapLocalFrameObject(ObjectIdx, Object.LocalOffset.getValue());
|
||||
if (parseStackObjectsDebugInfo(MF, PFS, Object, ObjectIdx))
|
||||
return true;
|
||||
}
|
||||
MFI.setCalleeSavedInfo(CSIInfo);
|
||||
if (!CSIInfo.empty())
|
||||
@ -522,6 +533,56 @@ bool MIRParserImpl::parseCalleeSavedRegister(
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Verify that given node is of a certain type. Return true on error.
|
||||
template <typename T>
|
||||
static bool typecheckMDNode(T *&Result, MDNode *Node,
|
||||
const yaml::StringValue &Source,
|
||||
StringRef TypeString, MIRParserImpl &Parser) {
|
||||
if (!Node)
|
||||
return false;
|
||||
Result = dyn_cast<T>(Node);
|
||||
if (!Result)
|
||||
return Parser.error(Source.SourceRange.Start,
|
||||
"expected a reference to a '" + TypeString +
|
||||
"' metadata node");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIRParserImpl::parseStackObjectsDebugInfo(
|
||||
MachineFunction &MF, PerFunctionMIParsingState &PFS,
|
||||
const yaml::MachineStackObject &Object, int FrameIdx) {
|
||||
// Debug information can only be attached to stack objects; Fixed stack
|
||||
// objects aren't supported.
|
||||
assert(FrameIdx >= 0 && "Expected a stack object frame index");
|
||||
MDNode *Var = nullptr, *Expr = nullptr, *Loc = nullptr;
|
||||
if (parseMDNode(Var, Object.DebugVar, MF, PFS) ||
|
||||
parseMDNode(Expr, Object.DebugExpr, MF, PFS) ||
|
||||
parseMDNode(Loc, Object.DebugLoc, MF, PFS))
|
||||
return true;
|
||||
if (!Var && !Expr && !Loc)
|
||||
return false;
|
||||
DILocalVariable *DIVar = nullptr;
|
||||
DIExpression *DIExpr = nullptr;
|
||||
DILocation *DILoc = nullptr;
|
||||
if (typecheckMDNode(DIVar, Var, Object.DebugVar, "DILocalVariable", *this) ||
|
||||
typecheckMDNode(DIExpr, Expr, Object.DebugExpr, "DIExpression", *this) ||
|
||||
typecheckMDNode(DILoc, Loc, Object.DebugLoc, "DILocation", *this))
|
||||
return true;
|
||||
MF.getMMI().setVariableDbgInfo(DIVar, DIExpr, unsigned(FrameIdx), DILoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIRParserImpl::parseMDNode(MDNode *&Node, const yaml::StringValue &Source,
|
||||
MachineFunction &MF,
|
||||
const PerFunctionMIParsingState &PFS) {
|
||||
if (Source.Value.empty())
|
||||
return false;
|
||||
SMDiagnostic Error;
|
||||
if (llvm::parseMDNode(Node, SM, MF, Source.Value, PFS, IRSlots, Error))
|
||||
return error(Error, Source.SourceRange);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIRParserImpl::initializeConstantPool(
|
||||
MachineConstantPool &ConstantPool, const yaml::MachineFunction &YamlMF,
|
||||
const MachineFunction &MF,
|
||||
|
@ -84,7 +84,8 @@ public:
|
||||
void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
|
||||
const MachineJumpTableInfo &JTI);
|
||||
void convertStackObjects(yaml::MachineFunction &MF,
|
||||
const MachineFrameInfo &MFI, ModuleSlotTracker &MST,
|
||||
const MachineFrameInfo &MFI, MachineModuleInfo &MMI,
|
||||
ModuleSlotTracker &MST,
|
||||
const TargetRegisterInfo *TRI);
|
||||
|
||||
private:
|
||||
@ -171,7 +172,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(), MST,
|
||||
convertStackObjects(YamlMF, *MF.getFrameInfo(), MF.getMMI(), MST,
|
||||
MF.getSubtarget().getRegisterInfo());
|
||||
if (const auto *ConstantPool = MF.getConstantPool())
|
||||
convert(YamlMF, *ConstantPool);
|
||||
@ -265,6 +266,7 @@ void MIRPrinter::convert(ModuleSlotTracker &MST,
|
||||
|
||||
void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
|
||||
const MachineFrameInfo &MFI,
|
||||
MachineModuleInfo &MMI,
|
||||
ModuleSlotTracker &MST,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
// Process fixed stack objects.
|
||||
@ -342,6 +344,29 @@ void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
|
||||
MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
|
||||
.printStackObjectReference(MFI.getStackProtectorIndex());
|
||||
}
|
||||
|
||||
// Print the debug variable information.
|
||||
for (MachineModuleInfo::VariableDbgInfo &DebugVar :
|
||||
MMI.getVariableDbgInfo()) {
|
||||
auto StackObjectInfo = StackObjectOperandMapping.find(DebugVar.Slot);
|
||||
assert(StackObjectInfo != StackObjectOperandMapping.end() &&
|
||||
"Invalid stack object index");
|
||||
const FrameIndexOperand &StackObject = StackObjectInfo->second;
|
||||
assert(!StackObject.IsFixed && "Expected a non-fixed stack object");
|
||||
auto &Object = MF.StackObjects[StackObject.ID];
|
||||
{
|
||||
raw_string_ostream StrOS(Object.DebugVar.Value);
|
||||
DebugVar.Var->printAsOperand(StrOS, MST);
|
||||
}
|
||||
{
|
||||
raw_string_ostream StrOS(Object.DebugExpr.Value);
|
||||
DebugVar.Expr->printAsOperand(StrOS, MST);
|
||||
}
|
||||
{
|
||||
raw_string_ostream StrOS(Object.DebugLoc.Value);
|
||||
DebugVar.Loc->printAsOperand(StrOS, MST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MIRPrinter::convert(yaml::MachineFunction &MF,
|
||||
|
@ -0,0 +1,25 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
--- |
|
||||
define i32 @test(i32 %x) {
|
||||
entry:
|
||||
%xa = alloca i32, align 4
|
||||
store i32 %x, i32* %xa, align 4
|
||||
%0 = load i32, i32* %xa, align 4
|
||||
ret i32 %0
|
||||
}
|
||||
...
|
||||
---
|
||||
name: test
|
||||
liveins:
|
||||
- { reg: '%edi' }
|
||||
stack:
|
||||
# CHECK: [[@LINE+1]]:74: expected a metadata node
|
||||
- { id: 0, name: xa, offset: -12, size: 4, alignment: 4, di-variable: '0' }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: %edi
|
||||
|
||||
MOV32mr %rsp, 1, _, -4, _, %edi :: (store 4 into %ir.xa)
|
||||
%eax = COPY killed %edi
|
||||
RETQ killed %eax
|
||||
...
|
53
test/CodeGen/MIR/X86/invalid-metadata-node-type.mir
Normal file
53
test/CodeGen/MIR/X86/invalid-metadata-node-type.mir
Normal file
@ -0,0 +1,53 @@
|
||||
# RUN: not llc -march=x86-64 -start-after machine-sink -stop-after machine-sink -o /dev/null %s 2>&1 | FileCheck %s
|
||||
--- |
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
|
||||
|
||||
define void @foo() #1 {
|
||||
entry:
|
||||
%x.i = alloca i8, align 1
|
||||
%y.i = alloca [256 x i8], align 16
|
||||
%0 = bitcast [256 x i8]* %y.i to i8*
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%1 = bitcast [256 x i8]* %y.i to i8*
|
||||
call void @llvm.dbg.declare(metadata i8* %0, metadata !4, metadata !7) #3, !dbg !8
|
||||
br label %for.body
|
||||
}
|
||||
|
||||
attributes #0 = { nounwind readnone }
|
||||
attributes #1 = { nounwind ssp uwtable }
|
||||
attributes #3 = { nounwind }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C89, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: 0, enums: !2, retainedTypes: !2)
|
||||
!1 = !DIFile(filename: "t.c", directory: "")
|
||||
!2 = !{}
|
||||
!3 = !{i32 1, !"Debug Info Version", i32 3}
|
||||
!4 = !DILocalVariable(name: "x", scope: !5, file: !1, line: 16, type: !6)
|
||||
!5 = !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false)
|
||||
!6 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
|
||||
!7 = !DIExpression()
|
||||
!8 = !DILocation(line: 0, scope: !5)
|
||||
...
|
||||
---
|
||||
name: foo
|
||||
isSSA: true
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 16
|
||||
stack:
|
||||
# CHECK: [[@LINE+1]]:75: expected a reference to a 'DILocalVariable' metadata node
|
||||
- { id: 0, name: y.i, offset: 0, size: 256, alignment: 16, di-variable: '!8',
|
||||
di-expression: '!7', di-location: '!8' }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
successors: %bb.1.for.body
|
||||
bb.1.for.body:
|
||||
successors: %bb.1.for.body
|
||||
|
||||
DBG_VALUE %stack.0.y.i, 0, !4, !7, debug-location !8
|
||||
JMP_1 %bb.1.for.body
|
||||
...
|
65
test/CodeGen/MIR/X86/stack-object-debug-info.mir
Normal file
65
test/CodeGen/MIR/X86/stack-object-debug-info.mir
Normal file
@ -0,0 +1,65 @@
|
||||
# RUN: llc -march=x86-64 -start-after machine-sink -stop-after machine-sink -o /dev/null %s | FileCheck %s
|
||||
# This test ensures that the MIR parser parses the stack object's debug info
|
||||
# correctly.
|
||||
--- |
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
|
||||
|
||||
define void @foo() #1 {
|
||||
entry:
|
||||
%x.i = alloca i8, align 1
|
||||
%y.i = alloca [256 x i8], align 16
|
||||
%0 = bitcast [256 x i8]* %y.i to i8*
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%1 = bitcast [256 x i8]* %y.i to i8*
|
||||
call void @llvm.lifetime.end(i64 -1, i8* %1) #3
|
||||
call void @llvm.lifetime.start(i64 -1, i8* %0) #3
|
||||
call void @llvm.dbg.declare(metadata i8* %0, metadata !4, metadata !7) #3, !dbg !8
|
||||
br label %for.body
|
||||
}
|
||||
|
||||
declare void @llvm.lifetime.start(i64, i8* nocapture) #2
|
||||
|
||||
declare void @llvm.lifetime.end(i64, i8* nocapture) #2
|
||||
|
||||
attributes #0 = { nounwind readnone }
|
||||
attributes #1 = { nounwind ssp uwtable }
|
||||
attributes #2 = { nounwind argmemonly }
|
||||
attributes #3 = { nounwind }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C89, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: 0, enums: !2, retainedTypes: !2)
|
||||
!1 = !DIFile(filename: "t.c", directory: "")
|
||||
!2 = !{}
|
||||
!3 = !{i32 1, !"Debug Info Version", i32 3}
|
||||
!4 = !DILocalVariable(name: "x", scope: !5, file: !1, line: 16, type: !6)
|
||||
!5 = !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false)
|
||||
!6 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
|
||||
!7 = !DIExpression()
|
||||
!8 = !DILocation(line: 0, scope: !5)
|
||||
...
|
||||
---
|
||||
name: foo
|
||||
isSSA: true
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 16
|
||||
# CHECK-LABEL: foo
|
||||
# CHECK: stack:
|
||||
# CHECK: - { id: 0, name: y.i, offset: 0, size: 256, alignment: 16, di-variable: '!4',
|
||||
# CHECK-NEXT: di-expression: '!7', di-location: '!8' }
|
||||
stack:
|
||||
- { id: 0, name: y.i, offset: 0, size: 256, alignment: 16, di-variable: '!4',
|
||||
di-expression: '!7', di-location: '!8' }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
successors: %bb.1.for.body
|
||||
bb.1.for.body:
|
||||
successors: %bb.1.for.body
|
||||
|
||||
DBG_VALUE %stack.0.y.i, 0, !4, !7, debug-location !8
|
||||
JMP_1 %bb.1.for.body
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user