diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/ABIInfo.h | 55 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 56 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 42 |
3 files changed, 111 insertions, 42 deletions
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index c059cb8baab..91b7742557f 100644 --- a/clang/lib/CodeGen/ABIInfo.h +++ b/clang/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!"); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 94a2ae9ee65..2ba44714c71 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -869,7 +869,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Direct: { // If we have the trivial case, handle it with no muss and fuss. if (!isa<llvm::StructType>(ArgI.getCoerceToType()) && - ArgI.getCoerceToType() == ConvertType(Ty)) { + ArgI.getCoerceToType() == ConvertType(Ty) && + ArgI.getDirectOffset() == 0) { assert(AI != Fn->arg_end() && "Argument mismatch!"); llvm::Value *V = AI; @@ -896,13 +897,21 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Alloca->setAlignment(AlignmentToUse); llvm::Value *V = Alloca; + llvm::Value *Ptr = V; // Pointer to store into. + + // If the value is offset in memory, apply the offset now. + if (unsigned Offs = ArgI.getDirectOffset()) { + Ptr = Builder.CreateBitCast(Ptr, Builder.getInt8PtrTy()); + Ptr = Builder.CreateConstGEP1_32(Ptr, Offs); + Ptr = Builder.CreateBitCast(Ptr, + llvm::PointerType::getUnqual(ArgI.getCoerceToType())); + } // If the coerce-to type is a first class aggregate, we flatten it and // pass the elements. Either way is semantically identical, but fast-isel // and the optimizer generally likes scalar values better than FCAs. if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType())) { - llvm::Value *Ptr = V; Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy)); for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { @@ -915,7 +924,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // Simple case, just do a coerced store of the argument into the alloca. assert(AI != Fn->arg_end() && "Argument mismatch!"); AI->setName(Arg->getName() + ".coerce"); - CreateCoercedStore(AI++, V, /*DestIsVolatile=*/false, *this); + CreateCoercedStore(AI++, Ptr, /*DestIsVolatile=*/false, *this); } @@ -992,8 +1001,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) { case ABIArgInfo::Extend: case ABIArgInfo::Direct: - - if (RetAI.getCoerceToType() == ConvertType(RetTy)) { + if (RetAI.getCoerceToType() == ConvertType(RetTy) && + RetAI.getDirectOffset() == 0) { // The internal return value temp always will have pointer-to-return-type // type, just do a load. @@ -1019,7 +1028,16 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) { } } } else { - RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this); + llvm::Value *V = ReturnValue; + // If the value is offset in memory, apply the offset now. + if (unsigned Offs = RetAI.getDirectOffset()) { + V = Builder.CreateBitCast(V, Builder.getInt8PtrTy()); + V = Builder.CreateConstGEP1_32(V, Offs); + V = Builder.CreateBitCast(V, + llvm::PointerType::getUnqual(RetAI.getCoerceToType())); + } + + RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this); } break; @@ -1142,7 +1160,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, case ABIArgInfo::Extend: case ABIArgInfo::Direct: { if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) && - ArgInfo.getCoerceToType() == ConvertType(info_it->type)) { + ArgInfo.getCoerceToType() == ConvertType(info_it->type) && + ArgInfo.getDirectOffset() == 0) { if (RV.isScalar()) Args.push_back(RV.getScalarVal()); else @@ -1161,6 +1180,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else SrcPtr = RV.getAggregateAddr(); + // If the value is offset in memory, apply the offset now. + if (unsigned Offs = ArgInfo.getDirectOffset()) { + SrcPtr = Builder.CreateBitCast(SrcPtr, Builder.getInt8PtrTy()); + SrcPtr = Builder.CreateConstGEP1_32(SrcPtr, Offs); + SrcPtr = Builder.CreateBitCast(SrcPtr, + llvm::PointerType::getUnqual(ArgInfo.getCoerceToType())); + + } + // If the coerce-to type is a first class aggregate, we flatten it and // pass the elements. Either way is semantically identical, but fast-isel // and the optimizer generally likes scalar values better than FCAs. @@ -1280,7 +1308,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, case ABIArgInfo::Extend: case ABIArgInfo::Direct: { - if (RetAI.getCoerceToType() == ConvertType(RetTy)) { + if (RetAI.getCoerceToType() == ConvertType(RetTy) && + RetAI.getDirectOffset() == 0) { if (RetTy->isAnyComplexType()) { llvm::Value *Real = Builder.CreateExtractValue(CI, 0); llvm::Value *Imag = Builder.CreateExtractValue(CI, 1); @@ -1308,7 +1337,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, DestIsVolatile = false; } - CreateCoercedStore(CI, DestPtr, DestIsVolatile, *this); + // If the value is offset in memory, apply the offset now. + llvm::Value *StorePtr = DestPtr; + if (unsigned Offs = RetAI.getDirectOffset()) { + StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy()); + StorePtr = Builder.CreateConstGEP1_32(StorePtr, Offs); + StorePtr = Builder.CreateBitCast(StorePtr, + llvm::PointerType::getUnqual(RetAI.getCoerceToType())); + } + CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); + if (RetTy->isAnyComplexType()) return RValue::getComplex(LoadComplexFromAddr(DestPtr, false)); if (CodeGenFunction::hasAggregateLLVMType(RetTy)) diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index be2e9540024..5ea77be07b7 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1015,11 +1015,6 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, if (Lo == Memory || Hi == Memory) break; } - - // If this record has no fields, no bases, no vtable, but isn't empty, - // classify as INTEGER. - if (CXXRD->isEmpty() && Size) - Current = Integer; } // Classify the fields one at a time, merging the results. @@ -1387,13 +1382,18 @@ classifyReturnType(QualType RetTy) const { // Check some invariants. assert((Hi != Memory || Lo == Memory) && "Invalid memory classification."); - assert((Lo != NoClass || Hi == NoClass) && "Invalid null classification."); assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification."); const llvm::Type *ResType = 0; switch (Lo) { case NoClass: - return ABIArgInfo::getIgnore(); + if (Hi == NoClass) + return ABIArgInfo::getIgnore(); + // If the low part is just padding, it takes no register, leave ResType + // null. + assert((Hi == SSE || Hi == Integer || Hi == X87Up) && + "Unknown missing lo part"); + break; case SSEUp: case X87Up: @@ -1461,12 +1461,18 @@ classifyReturnType(QualType RetTy) const { case Integer: { const llvm::Type *HiType = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8, RetTy, 8); + if (Lo == NoClass) // Return HiType at offset 8 in memory. + return ABIArgInfo::getDirect(HiType, 8); + ResType = llvm::StructType::get(getVMContext(), ResType, HiType, NULL); break; } case SSE: { const llvm::Type *HiType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8, RetTy, 8); + if (Lo == NoClass) // Return HiType at offset 8 in memory. + return ABIArgInfo::getDirect(HiType, 8); + ResType = llvm::StructType::get(getVMContext(), ResType, HiType,NULL); break; } @@ -1490,6 +1496,9 @@ classifyReturnType(QualType RetTy) const { if (Lo != X87) { const llvm::Type *HiType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8, RetTy, 8); + if (Lo == NoClass) // Return HiType at offset 8 in memory. + return ABIArgInfo::getDirect(HiType, 8); + ResType = llvm::StructType::get(getVMContext(), ResType, HiType, NULL); } break; @@ -1506,7 +1515,6 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, // Check some invariants. // FIXME: Enforce these by construction. assert((Hi != Memory || Lo == Memory) && "Invalid memory classification."); - assert((Lo != NoClass || Hi == NoClass) && "Invalid null classification."); assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification."); neededInt = 0; @@ -1514,8 +1522,14 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, const llvm::Type *ResType = 0; switch (Lo) { case NoClass: - return ABIArgInfo::getIgnore(); - + if (Hi == NoClass) + return ABIArgInfo::getIgnore(); + // If the low part is just padding, it takes no register, leave ResType + // null. + assert((Hi == SSE || Hi == Integer || Hi == X87Up) && + "Unknown missing lo part"); + break; + // AMD64-ABI 3.2.3p3: Rule 1. If the class is MEMORY, pass the argument // on the stack. case Memory: @@ -1579,6 +1593,10 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, // Pick an 8-byte type based on the preferred type. const llvm::Type *HiType = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8, Ty, 8); + + if (Lo == NoClass) // Pass HiType at offset 8 in memory. + return ABIArgInfo::getDirect(HiType, 8); + ResType = llvm::StructType::get(getVMContext(), ResType, HiType, NULL); break; } @@ -1589,6 +1607,10 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, case SSE: { const llvm::Type *HiType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8, Ty, 8); + + if (Lo == NoClass) // Pass HiType at offset 8 in memory. + return ABIArgInfo::getDirect(HiType, 8); + ResType = llvm::StructType::get(getVMContext(), ResType, HiType, NULL); ++neededSSE; break; |