Skip to content

Commit

Permalink
[MIPS] fix extension of integer types (function calls)
Browse files Browse the repository at this point in the history
On MIPS unsigned int type should not be zero extended but sign-extended.

Patch by Strahinja Petrovic.

Differential Revision: http://reviews.llvm.org/D9198

llvm-svn: 238200
  • Loading branch information
petar-jovanovic committed May 26, 2015
1 parent 0af4f63 commit 9aa0f16
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 8 deletions.
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/ABIInfo.h
Expand Up @@ -87,6 +87,8 @@ namespace clang {
virtual bool isHomogeneousAggregateSmallEnough(const Type *Base,
uint64_t Members) const;

virtual bool shouldSignExtUnsignedType(QualType Ty) const;

bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t &Members) const;

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/CodeGen/CGCall.cpp
Expand Up @@ -1588,8 +1588,12 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
case ABIArgInfo::Extend:
if (ParamType->isSignedIntegerOrEnumerationType())
Attrs.addAttribute(llvm::Attribute::SExt);
else if (ParamType->isUnsignedIntegerOrEnumerationType())
Attrs.addAttribute(llvm::Attribute::ZExt);
else if (ParamType->isUnsignedIntegerOrEnumerationType()) {
if (getTypes().getABIInfo().shouldSignExtUnsignedType(ParamType))
Attrs.addAttribute(llvm::Attribute::SExt);
else
Attrs.addAttribute(llvm::Attribute::ZExt);
}
// FALL THROUGH
case ABIArgInfo::Direct:
if (ArgNo == 0 && FI.isChainCall())
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/TargetInfo.cpp
Expand Up @@ -108,6 +108,10 @@ bool ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
return false;
}

bool ABIInfo::shouldSignExtUnsignedType(QualType Ty) const {
return false;
}

void ABIArgInfo::dump() const {
raw_ostream &OS = llvm::errs();
OS << "(ABIArgInfo Kind=";
Expand Down Expand Up @@ -5547,6 +5551,7 @@ class MipsABIInfo : public ABIInfo {
void computeInfo(CGFunctionInfo &FI) const override;
llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const override;
bool shouldSignExtUnsignedType(QualType Ty) const override;
};

class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
Expand Down Expand Up @@ -5849,6 +5854,16 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
return AddrTyped;
}

bool MipsABIInfo::shouldSignExtUnsignedType(QualType Ty) const {
int TySize = getContext().getTypeSize(Ty);

// MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
return true;

return false;
}

bool
MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
llvm::Value *Address) const {
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/atomics-inlining.c
Expand Up @@ -76,8 +76,8 @@ void test1(void) {
// MIPS32: store atomic i32 {{.*}}, i32* @i1 seq_cst
// MIPS32: call i64 @__atomic_load_8(i8* bitcast (i64* @ll1 to i8*)
// MIPS32: call void @__atomic_store_8(i8* bitcast (i64* @ll1 to i8*), i64
// MIPS32: call void @__atomic_load(i32 zeroext 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)
// MIPS32: call void @__atomic_store(i32 zeroext 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)
// MIPS32: call void @__atomic_load(i32 signext 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)
// MIPS32: call void @__atomic_store(i32 signext 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)

// MIPS64-LABEL: define void @test1
// MIPS64: = load atomic i8, i8* @c1 seq_cst
Expand Down
22 changes: 22 additions & 0 deletions clang/test/CodeGen/mips-unsigned-ext-var.c
@@ -0,0 +1,22 @@
// RUN: %clang -target mips64-unknown-linux -O2 -mabi=n64 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=N64
// RUN: %clang -target mips64-unknown-linux -O2 -mabi=n32 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=N32
// RUN: %clang -target mips-unknown-linux -O2 -mabi=o32 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=O32

#include <stdarg.h>

unsigned foo(int x, ...) {
va_list valist;
va_start(valist, x);
unsigned a;
a = va_arg(valist, unsigned);
return a;
}

void foo1() {
unsigned f = 0xffffffe0;
foo(1,f);
}

//N64: call i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
//N32: call i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
//O32: call i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
15 changes: 15 additions & 0 deletions clang/test/CodeGen/mips-unsigned-extend.c
@@ -0,0 +1,15 @@
// RUN: %clang -target mips64-unknown-linux -O0 -mabi=n64 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=N64
// RUN: %clang -target mips64-unknown-linux -O0 -mabi=n32 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=N32
// RUN: %clang -target mips-unknown-linux -O0 -mabi=o32 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=O32

void foo(unsigned a) {
}

void foo1() {
unsigned f = 0xffffffe0;
foo(f);
}

// N64: call void @foo(i32 signext %0)
// N32: call void @foo(i32 signext %0)
// O32: call void @foo(i32 signext %0)
8 changes: 4 additions & 4 deletions clang/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp
Expand Up @@ -10,10 +10,10 @@ long *alloc_long() {
return rv;
}
// O32-LABEL: define i32* @_Z10alloc_longv()
// O32: call noalias i8* @_Znwj(i32 zeroext 4)
// O32: call noalias i8* @_Znwj(i32 signext 4)

// N32-LABEL: define i32* @_Z10alloc_longv()
// N32: call noalias i8* @_Znwj(i32 zeroext 4)
// N32: call noalias i8* @_Znwj(i32 signext 4)

// N64-LABEL: define i64* @_Z10alloc_longv()
// N64: call noalias i8* @_Znwm(i64 zeroext 8)
Expand All @@ -24,10 +24,10 @@ long *alloc_long_array() {
}

// O32-LABEL: define i32* @_Z16alloc_long_arrayv()
// O32: call noalias i8* @_Znaj(i32 zeroext 8)
// O32: call noalias i8* @_Znaj(i32 signext 8)

// N32-LABEL: define i32* @_Z16alloc_long_arrayv()
// N32: call noalias i8* @_Znaj(i32 zeroext 8)
// N32: call noalias i8* @_Znaj(i32 signext 8)

// N64-LABEL: define i64* @_Z16alloc_long_arrayv()
// N64: call noalias i8* @_Znam(i64 zeroext 16)
Expand Down

0 comments on commit 9aa0f16

Please sign in to comment.