void Win64TargetABI::rewriteArgument(IrFuncTy& fty, IrFuncTyArg& arg) { LLType* originalLType = arg.ltype; Type* t = arg.type->toBasetype(); if (isPassedWithByvalSemantics(t)) { // these types are passed byval: // the caller allocates a copy and then passes a pointer to the copy arg.rewrite = &byvalRewrite; arg.ltype = byvalRewrite.type(arg.type, arg.ltype); // the copy is treated as a local variable of the callee // hence add the NoAlias and NoCapture attributes arg.attrs.clear() .add(LDC_ATTRIBUTE(NoAlias)) .add(LDC_ATTRIBUTE(NoCapture)); } else if (isAggregate(t) && canRewriteAsInt(t) && !IntegerRewrite::isObsoleteFor(originalLType)) { arg.rewrite = &integerRewrite; arg.ltype = integerRewrite.type(arg.type, arg.ltype); } IF_LOG if (arg.rewrite) { Logger::println("Rewriting argument type %s", t->toChars()); LOG_SCOPE; Logger::cout() << *originalLType << " => " << *arg.ltype << '\n'; } }
void rewriteArgument(IrFuncTy& fty, IrFuncTyArg& arg) { Type* ty = arg.type->toBasetype(); if (ty->ty == Tstruct || ty->ty == Tsarray) { if (canRewriteAsInt(ty)) { arg.rewrite = &integerRewrite; arg.ltype = integerRewrite.type(arg.type, arg.ltype); } else { // these types are passed byval: // the caller allocates a copy and then passes a pointer to the copy arg.rewrite = &byvalRewrite; arg.ltype = byvalRewrite.type(arg.type, arg.ltype); // the copy is treated as a local variable of the callee // hence add the NoAlias and NoCapture attributes arg.attrs.clear() .add(LDC_ATTRIBUTE(NoAlias)) .add(LDC_ATTRIBUTE(NoCapture)); } } }
// Returns true if the D type is passed byval (the callee getting a pointer // to a dedicated hidden copy). bool isPassedWithByvalSemantics(Type *t) const { return // * aggregates which can NOT be rewritten as integers // (size > 8 bytes or not a power of 2) (isAggregate(t) && !canRewriteAsInt(t)) || // * 80-bit real and ireal (realIs80bits() && (t->ty == Tfloat80 || t->ty == Timaginary80)); }
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override { Type *ty = arg.type->toBasetype(); if (ty->ty == Tstruct || ty->ty == Tsarray) { if (ty->ty == Tstruct && isHFA((TypeStruct *)ty, &arg.ltype, 8)) { arg.rewrite = &hfaToArray; arg.ltype = hfaToArray.type(arg.type); } else if (canRewriteAsInt(ty, true)) { arg.rewrite = &integerRewrite; arg.ltype = integerRewrite.type(arg.type); } else { arg.rewrite = &compositeToArray64; arg.ltype = compositeToArray64.type(arg.type); } } else if (ty->isintegral()) { arg.attrs.add(ty->isunsigned() ? LLAttribute::ZExt : LLAttribute::SExt); } }
void rewriteArgument(IrFuncTy &fty, IrFuncTyArg &arg) override { Type *ty = arg.type->toBasetype(); if (ty->ty == Tstruct || ty->ty == Tsarray) { if (canRewriteAsInt(ty, Is64Bit)) { if (!IntegerRewrite::isObsoleteFor(arg.ltype)) { arg.rewrite = &integerRewrite; arg.ltype = integerRewrite.type(arg.type, arg.ltype); } } else { // these types are passed byval: // the caller allocates a copy and then passes a pointer to the copy arg.rewrite = &byvalRewrite; arg.ltype = byvalRewrite.type(arg.type, arg.ltype); // the copy is treated as a local variable of the callee // hence add the NoAlias and NoCapture attributes arg.attrs.clear() .add(LLAttribute::NoAlias) .add(LLAttribute::NoCapture) .addAlignment(byvalRewrite.alignment(arg.type)); } } }