summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/ABIInfo.h
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-07-30 04:02:24 +0000
committerChris Lattner <sabre@nondot.org>2010-07-30 04:02:24 +0000
commit117e3f4cd4d6ea41c3202da8729f94168c5c8239 (patch)
tree0425d5c3eddc8a6b289b382ef947aaf875985210 /lib/CodeGen/ABIInfo.h
parent98406a953a00a96a7a2fad5509fde1bfc7b15e3d (diff)
fix PR5179 and correctly fix PR5831 to not miscompile.
The X86-64 ABI code didn't handle the case when a struct would get classified and turn up as "NoClass INTEGER" for example. This is perfectly possible when the first slot is all padding (e.g. due to empty base classes). In this situation, the first 8-byte doesn't take a register at all, only the second 8-byte does. This fixes this by enhancing the x86-64 abi stuff to allow and handle this case, reverts the broken fix for PR5831, and enhances the target independent stuff to be able to handle an argument value in registers being accessed at an offset from the memory value. This is the last x86-64 calling convention related miscompile that I'm aware of. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109848 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/ABIInfo.h')
-rw-r--r--lib/CodeGen/ABIInfo.h55
1 files changed, 32 insertions, 23 deletions
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h
index c059cb8baa..91b7742557 100644
--- a/lib/CodeGen/ABIInfo.h
+++ b/lib/CodeGen/ABIInfo.h
@@ -38,26 +38,30 @@ namespace clang {
class ABIArgInfo {
public:
enum Kind {
- Direct, /// Pass the argument directly using the normal converted LLVM
- /// type, or by coercing to another specified type
- /// (stored in 'CoerceToType').
-
- Extend, /// Valid only for integer argument types. Same as 'direct'
- /// but also emit a zero/sign extension attribute.
-
- Indirect, /// Pass the argument indirectly via a hidden pointer
- /// with the specified alignment (0 indicates default
- /// alignment).
-
- Ignore, /// Ignore the argument (treat as void). Useful for
- /// void and empty structs.
-
- Expand, /// Only valid for aggregate argument types. The
- /// structure should be expanded into consecutive
- /// arguments for its constituent fields. Currently
- /// expand is only allowed on structures whose fields
- /// are all scalar types or are themselves expandable
- /// types.
+ /// Direct - Pass the argument directly using the normal converted LLVM
+ /// type, or by coercing to another specified type stored in
+ /// 'CoerceToType'). If an offset is specified (in UIntData), then the
+ /// argument passed is offset by some number of bytes in the memory
+ /// representation.
+ Direct,
+
+ /// Extend - Valid only for integer argument types. Same as 'direct'
+ /// but also emit a zero/sign extension attribute.
+ Extend,
+
+ /// Indirect - Pass the argument indirectly via a hidden pointer
+ /// with the specified alignment (0 indicates default alignment).
+ Indirect,
+
+ /// Ignore - Ignore the argument (treat as void). Useful for void and
+ /// empty structs.
+ Ignore,
+
+ /// Expand - Only valid for aggregate argument types. The structure should
+ /// be expanded into consecutive arguments for its constituent fields.
+ /// Currently expand is only allowed on structures whose fields
+ /// are all scalar types or are themselves expandable types.
+ Expand,
KindFirst=Direct, KindLast=Expand
};
@@ -75,11 +79,11 @@ namespace clang {
public:
ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
- static ABIArgInfo getDirect(const llvm::Type *T = 0) {
- return ABIArgInfo(Direct, T);
+ static ABIArgInfo getDirect(const llvm::Type *T = 0, unsigned Offset = 0) {
+ return ABIArgInfo(Direct, T, Offset);
}
static ABIArgInfo getExtend(const llvm::Type *T = 0) {
- return ABIArgInfo(Extend, T);
+ return ABIArgInfo(Extend, T, 0);
}
static ABIArgInfo getIgnore() {
return ABIArgInfo(Ignore);
@@ -103,6 +107,10 @@ namespace clang {
}
// Direct/Extend accessors
+ unsigned getDirectOffset() const {
+ assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+ return UIntData;
+ }
const llvm::Type *getCoerceToType() const {
assert(canHaveCoerceToType() && "Invalid kind!");
return TypeData;
@@ -112,6 +120,7 @@ namespace clang {
assert(canHaveCoerceToType() && "Invalid kind!");
TypeData = T;
}
+
// Indirect accessors
unsigned getIndirectAlign() const {
assert(TheKind == Indirect && "Invalid kind!");