public:
enum Kind {
Direct, /// Pass the argument directly using the normal
- /// converted LLVM type.
-
- StructRet, /// Only valid for return values. The return value
- /// should be passed through a pointer to a caller
- /// allocated location passed as an implicit first
- /// argument to the function.
+ /// converted LLVM type. Complex and structure types
+ /// are passed using first class aggregates.
+
+ 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.
Coerce, /// Only valid for aggregate return types, the argument
/// should be accessed by coercion to a provided type.
- ByVal, /// Only valid for aggregate argument types. The
- /// structure should be passed "byval" with the
- /// specified alignment (0 indicates default
- /// alignment).
-
Expand, /// Only valid for aggregate argument types. The
/// structure should be expanded into consecutive
/// arguments for its constituent fields. Currently
static ABIArgInfo getDirect() {
return ABIArgInfo(Direct);
}
- static ABIArgInfo getStructRet() {
- return ABIArgInfo(StructRet);
- }
static ABIArgInfo getIgnore() {
return ABIArgInfo(Ignore);
}
static ABIArgInfo getCoerce(const llvm::Type *T) {
return ABIArgInfo(Coerce, T);
}
- static ABIArgInfo getByVal(unsigned Alignment) {
- return ABIArgInfo(ByVal, 0, Alignment);
+ static ABIArgInfo getIndirect(unsigned Alignment) {
+ return ABIArgInfo(Indirect, 0, Alignment);
}
static ABIArgInfo getExpand() {
return ABIArgInfo(Expand);
Kind getKind() const { return TheKind; }
bool isDirect() const { return TheKind == Direct; }
- bool isStructRet() const { return TheKind == StructRet; }
bool isIgnore() const { return TheKind == Ignore; }
bool isCoerce() const { return TheKind == Coerce; }
- bool isByVal() const { return TheKind == ByVal; }
+ bool isIndirect() const { return TheKind == Indirect; }
bool isExpand() const { return TheKind == Expand; }
// Coerce accessors
}
// ByVal accessors
- unsigned getByValAlignment() const {
- assert(TheKind == ByVal && "Invalid kind!");
+ unsigned getIndirectAlign() const {
+ assert(TheKind == Indirect && "Invalid kind!");
return UIntData;
}
case Direct:
fprintf(stderr, "Direct");
break;
- case StructRet:
- fprintf(stderr, "StructRet");
- break;
case Ignore:
fprintf(stderr, "Ignore");
break;
// FIXME: This is ridiculous.
llvm::errs().flush();
break;
- case ByVal:
- fprintf(stderr, "ByVal Align=%d", getByValAlignment());
+ case Indirect:
+ fprintf(stderr, "Indirect Align=%d", getIndirectAlign());
break;
case Expand:
fprintf(stderr, "Expand");
} else if (Size == 64) {
return ABIArgInfo::getCoerce(llvm::Type::Int64Ty);
} else {
- return ABIArgInfo::getStructRet();
+ return ABIArgInfo::getIndirect(0);
}
} else {
return ABIArgInfo::getDirect();
ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
ASTContext &Context) const {
- // FIXME: Set alignment on byval arguments.
+ // FIXME: Set alignment on indirect arguments.
if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
- // Structures with flexible arrays are always byval.
+ // Structures with flexible arrays are always indirect.
if (const RecordType *RT = Ty->getAsStructureType())
if (RT->getDecl()->hasFlexibleArrayMember())
- return ABIArgInfo::getByVal(0);
+ return ABIArgInfo::getIndirect(0);
// Ignore empty structs.
uint64_t Size = Context.getTypeSize(Ty);
return ABIArgInfo::getExpand();
}
- return ABIArgInfo::getByVal(0);
+ return ABIArgInfo::getIndirect(0);
} else {
return ABIArgInfo::getDirect();
}
assert(0 && "Invalid classification for lo word.");
// AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via
- // hidden argument, i.e. structret.
+ // hidden argument.
case Memory:
- return ABIArgInfo::getStructRet();
+ return ABIArgInfo::getIndirect(0);
// AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next
// available register of the sequence %rax, %rdx is used.
case ComplexX87:
// Choose appropriate in memory type.
if (CodeGenFunction::hasAggregateLLVMType(Ty))
- return ABIArgInfo::getByVal(0);
+ return ABIArgInfo::getIndirect(0);
else
return ABIArgInfo::getDirect();
} else {
// Choose appropriate in memory type.
if (CodeGenFunction::hasAggregateLLVMType(Ty))
- return ABIArgInfo::getByVal(0);
+ return ABIArgInfo::getIndirect(0);
else
return ABIArgInfo::getDirect();
}
if (RetTy->isVoidType()) {
return ABIArgInfo::getIgnore();
} else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
- return ABIArgInfo::getStructRet();
+ return ABIArgInfo::getIndirect(0);
} else {
return ABIArgInfo::getDirect();
}
ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
ASTContext &Context) const {
if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
- return ABIArgInfo::getByVal(0);
+ return ABIArgInfo::getIndirect(0);
} else {
return ABIArgInfo::getDirect();
}
/***/
bool CodeGenModule::ReturnTypeUsesSret(const CGFunctionInfo &FI) {
- return FI.getReturnInfo().isStructRet();
+ return FI.getReturnInfo().isIndirect();
}
const llvm::FunctionType *
QualType RetTy = FI.getReturnType();
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
- case ABIArgInfo::ByVal:
case ABIArgInfo::Expand:
assert(0 && "Invalid ABI kind for return argument");
ResultType = ConvertType(RetTy);
break;
- case ABIArgInfo::StructRet: {
+ case ABIArgInfo::Indirect: {
+ assert(!RetAI.getIndirectAlign() && "Align unused on indirect return.");
ResultType = llvm::Type::VoidTy;
const llvm::Type *STy = ConvertType(RetTy);
ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace()));
ArgTys.push_back(AI.getCoerceToType());
break;
- case ABIArgInfo::StructRet:
- assert(0 && "Invalid ABI kind for non-return argument");
-
- case ABIArgInfo::ByVal:
- // byval arguments are always on the stack, which is addr space #0.
+ case ABIArgInfo::Indirect:
+ // indirect arguments are always on the stack, which is addr space #0.
ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
break;
}
break;
- case ABIArgInfo::StructRet:
+ case ABIArgInfo::Indirect:
PAL.push_back(llvm::AttributeWithIndex::get(Index,
llvm::Attribute::StructRet |
llvm::Attribute::NoAlias));
case ABIArgInfo::Coerce:
break;
- case ABIArgInfo::ByVal:
case ABIArgInfo::Expand:
assert(0 && "Invalid ABI kind for return argument");
}
unsigned Attributes = 0;
switch (AI.getKind()) {
- case ABIArgInfo::StructRet:
- assert(0 && "Invalid ABI kind for non-return argument");
-
case ABIArgInfo::Coerce:
break;
- case ABIArgInfo::ByVal:
+ case ABIArgInfo::Indirect:
Attributes |= llvm::Attribute::ByVal;
Attributes |=
- llvm::Attribute::constructAlignmentFromInt(AI.getByValAlignment());
+ llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
break;
case ABIArgInfo::Direct:
const ABIArgInfo &ArgI = info_it->info;
switch (ArgI.getKind()) {
- case ABIArgInfo::ByVal:
+ // FIXME: Implement correct [in]direct semantics.
+ case ABIArgInfo::Indirect:
case ABIArgInfo::Direct: {
assert(AI != Fn->arg_end() && "Argument mismatch!");
llvm::Value* V = AI;
EmitParmDecl(*Arg, V);
break;
}
-
- case ABIArgInfo::StructRet:
- assert(0 && "Invalid ABI kind for non-return argument");
}
++AI;
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
- case ABIArgInfo::StructRet:
+ // FIXME: Implement correct [in]direct semantics.
+ case ABIArgInfo::Indirect:
if (RetTy->isAnyComplexType()) {
// FIXME: Volatile
ComplexPairTy RT = LoadComplexFromAddr(ReturnValue, false);
break;
}
- case ABIArgInfo::ByVal:
case ABIArgInfo::Expand:
assert(0 && "Invalid ABI kind for return argument");
}
QualType RetTy = CallInfo.getReturnType();
const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
switch (RetAI.getKind()) {
- case ABIArgInfo::StructRet:
+ case ABIArgInfo::Indirect:
// Create a temporary alloca to hold the result of the call. :(
Args.push_back(CreateTempAlloca(ConvertType(RetTy)));
break;
case ABIArgInfo::Coerce:
break;
- case ABIArgInfo::ByVal:
case ABIArgInfo::Expand:
assert(0 && "Invalid ABI kind for return argument");
}
RValue RV = I->first;
switch (ArgInfo.getKind()) {
- case ABIArgInfo::ByVal: // Direct is byval
+ // FIXME: Implement correct [in]direct semantics.
+ case ABIArgInfo::Indirect:
case ABIArgInfo::Direct:
if (RV.isScalar()) {
Args.push_back(RV.getScalarVal());
break;
}
- case ABIArgInfo::StructRet:
- assert(0 && "Invalid ABI kind for non-return argument");
- break;
-
case ABIArgInfo::Expand:
ExpandTypeToArgs(I->second, RV, Args);
break;
CI->setName("call");
switch (RetAI.getKind()) {
- case ABIArgInfo::StructRet:
+ // FIXME: Implement correct [in]direct semantics.
+ case ABIArgInfo::Indirect:
if (RetTy->isAnyComplexType())
return RValue::getComplex(LoadComplexFromAddr(Args[0], false));
else if (CodeGenFunction::hasAggregateLLVMType(RetTy))
return RValue::get(Builder.CreateLoad(V));
}
- case ABIArgInfo::ByVal:
case ABIArgInfo::Expand:
assert(0 && "Invalid ABI kind for return argument");
}