# Changeset View

Changeset View

# Standalone View

Standalone View

# clang/lib/CodeGen/CGBuiltin.cpp

Show First 20 Lines • Show All 492 Lines • ▼ Show 20 Line(s) | 1462 | RValue CodeGenFunction::emitRotate(const CallExpr *E, bool IsRotateRight) { | |||
---|---|---|---|---|---|

1469 | ShiftAmt = Builder.CreateIntCast(ShiftAmt, Ty, false); | 1469 | ShiftAmt = Builder.CreateIntCast(ShiftAmt, Ty, false); | ||

1470 | 1470 | | |||

1471 | // Rotate is a special case of LLVM funnel shift - 1st 2 args are the same. | 1471 | // Rotate is a special case of LLVM funnel shift - 1st 2 args are the same. | ||

1472 | unsigned IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl; | 1472 | unsigned IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl; | ||

1473 | Function *F = CGM.getIntrinsic(IID, Ty); | 1473 | Function *F = CGM.getIntrinsic(IID, Ty); | ||

1474 | return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt })); | 1474 | return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt })); | ||

1475 | } | 1475 | } | ||

1476 | 1476 | | |||

1477 | /// For a call to a builtin C standard library function, emit a call to a | ||||

1478 | /// fortified variant using __builtin_object_size. For instance, instead of | ||||

1479 | /// emitting `sprintf(buf, "%d", 32)`, this function would emit | ||||

1480 | /// `__sprintf_chk(buf, Flag, __builtin_object_size(buf, 0), "%d", 32)`. | ||||

1481 | RValue CodeGenFunction::emitFortifiedStdLibCall(CodeGenFunction &CGF, | ||||

1482 | const CallExpr *CE, | ||||

1483 | unsigned BuiltinID, | ||||

1484 | unsigned BOSType, | ||||

1485 | unsigned Flag) { | ||||

1486 | SmallVector<llvm::Value *, 8> ArgVals; | ||||

1487 | for (const Expr *Arg : CE->arguments()) | ||||

1488 | ArgVals.push_back(EmitScalarExpr(Arg)); | ||||

1489 | | ||||

1490 | llvm::Value *FlagVal = llvm::ConstantInt::get(IntTy, Flag); | ||||

rjmccall: Could you move the body of this into a helper function? This function is really far too large… | |||||

1491 | auto emitObjSize = [&]() -> llvm::Value * { | ||||

Done ReplyIs the explicit trailing return here needed? I would have assumed this could be inferred. aaron.ballman: Is the explicit trailing return here needed? I would have assumed this could be inferred. | |||||

1492 | return evaluateOrEmitBuiltinObjectSize(CE->getArg(0), BOSType, SizeTy, | ||||

1493 | ArgVals[0], false); | ||||

1494 | }; | ||||

1495 | | ||||

1496 | unsigned FortifiedVariantID = Builtin::getFortifiedVariantFunction(BuiltinID); | ||||

1497 | assert(FortifiedVariantID != 0 && "Should be diagnosed in Sema"); | ||||

1498 | | ||||

1499 | // Adjust ArgVals to include a __builtin_object_size(n) or flag argument at | ||||

1500 | // the right position. Variadic printf-like functions take a flag and object | ||||

1501 | // size (if they're printing to a string) before the format string, and all | ||||

1502 | // other functions just take the object size as their last argument. The | ||||

1503 | // object size, if present, always corresponds to the first argument. | ||||

1504 | switch (BuiltinID) { | ||||

1505 | case Builtin::BImemcpy: | ||||

1506 | case Builtin::BImemmove: | ||||

1507 | case Builtin::BImemset: | ||||

1508 | case Builtin::BIstpcpy: | ||||

1509 | case Builtin::BIstrcat: | ||||

1510 | case Builtin::BIstrcpy: | ||||

1511 | case Builtin::BIstrlcat: | ||||

1512 | case Builtin::BIstrlcpy: | ||||

1513 | case Builtin::BIstrncat: | ||||

1514 | case Builtin::BIstrncpy: | ||||

1515 | case Builtin::BIstpncpy: | ||||

1516 | ArgVals.push_back(emitObjSize()); | ||||

Done ReplyI think this might be over-commented. :) Could you just put smaller comments on groups of cases, like: // All of these take the destination object size as the final argument. or // These take flags and the destination object size immediately before the format string. rjmccall: I think this might be over-commented. :)
Could you just put smaller comments on groups of… | |||||

1517 | break; | ||||

1518 | | ||||

1519 | case Builtin::BIsnprintf: | ||||

1520 | case Builtin::BIvsnprintf: | ||||

1521 | ArgVals.insert(ArgVals.begin() + 2, FlagVal); | ||||

1522 | ArgVals.insert(ArgVals.begin() + 3, emitObjSize()); | ||||

1523 | break; | ||||

1524 | | ||||

1525 | case Builtin::BIsprintf: | ||||

1526 | case Builtin::BIvsprintf: | ||||

1527 | ArgVals.insert(ArgVals.begin() + 1, FlagVal); | ||||

1528 | ArgVals.insert(ArgVals.begin() + 2, emitObjSize()); | ||||

1529 | break; | ||||

1530 | | ||||

1531 | case Builtin::BIfprintf: | ||||

1532 | case Builtin::BIvfprintf: | ||||

1533 | ArgVals.insert(ArgVals.begin() + 1, FlagVal); | ||||

1534 | break; | ||||

1535 | | ||||

1536 | case Builtin::BIprintf: | ||||

1537 | case Builtin::BIvprintf: | ||||

1538 | ArgVals.insert(ArgVals.begin(), FlagVal); | ||||

1539 | break; | ||||

1540 | | ||||

1541 | default: | ||||

1542 | llvm_unreachable("Unknown fortified builtin?"); | ||||

1543 | } | ||||

1544 | | ||||

1545 | ASTContext::GetBuiltinTypeError Err; | ||||

1546 | QualType VariantTy = getContext().GetBuiltinType(FortifiedVariantID, Err); | ||||

1547 | assert(Err == ASTContext::GE_None && "Should not codegen an error"); | ||||

1548 | llvm::FunctionType *LLVMVariantTy = | ||||

Done Reply
aaron.ballman: `auto *` | |||||

1549 | cast<llvm::FunctionType>(ConvertType(VariantTy)); | ||||

1550 | StringRef VariantName = getContext().BuiltinInfo.getName(FortifiedVariantID) + | ||||

1551 | strlen("__builtin_"); | ||||

1552 | | ||||

1553 | llvm::Value *V = Builder.CreateCall( | ||||

1554 | CGM.CreateRuntimeFunction(LLVMVariantTy, VariantName), ArgVals); | ||||

1555 | return RValue::get(V); | ||||

1556 | } | ||||

1557 | | ||||

1477 | RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, | 1558 | RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, | ||

1478 | const CallExpr *E, | 1559 | const CallExpr *E, | ||

1479 | ReturnValueSlot ReturnValue) { | 1560 | ReturnValueSlot ReturnValue) { | ||

1480 | const FunctionDecl *FD = GD.getDecl()->getAsFunction(); | 1561 | const FunctionDecl *FD = GD.getDecl()->getAsFunction(); | ||

1481 | // See if we can constant fold this builtin. If so, don't emit it at all. | 1562 | // See if we can constant fold this builtin. If so, don't emit it at all. | ||

1482 | Expr::EvalResult Result; | 1563 | Expr::EvalResult Result; | ||

1483 | if (E->EvaluateAsRValue(Result, CGM.getContext()) && | 1564 | if (E->EvaluateAsRValue(Result, CGM.getContext()) && | ||

1484 | !Result.hasSideEffects()) { | 1565 | !Result.hasSideEffects()) { | ||

1485 | if (Result.Val.isInt()) | 1566 | if (Result.Val.isInt()) | ||

1486 | return RValue::get(llvm::ConstantInt::get(getLLVMContext(), | 1567 | return RValue::get(llvm::ConstantInt::get(getLLVMContext(), | ||

1487 | Result.Val.getInt())); | 1568 | Result.Val.getInt())); | ||

1488 | if (Result.Val.isFloat()) | 1569 | if (Result.Val.isFloat()) | ||

1489 | return RValue::get(llvm::ConstantFP::get(getLLVMContext(), | 1570 | return RValue::get(llvm::ConstantFP::get(getLLVMContext(), | ||

1490 | Result.Val.getFloat())); | 1571 | Result.Val.getFloat())); | ||

1491 | } | 1572 | } | ||

1492 | 1573 | | |||

1574 | if (auto *Attr = FD->getAttr<FortifyStdLibAttr>()) | ||||

Done Reply
aaron.ballman: `const auto *` and some other identifier than `Attr` (so it won't conflict with the type name). | |||||

1575 | return emitFortifiedStdLibCall(*this, E, BuiltinID, Attr->getType(), | ||||

1576 | Attr->getFlag()); | ||||

1577 | | ||||

1493 | // There are LLVM math intrinsics/instructions corresponding to math library | 1578 | // There are LLVM math intrinsics/instructions corresponding to math library | ||

1494 | // functions except the LLVM op will never set errno while the math library | 1579 | // functions except the LLVM op will never set errno while the math library | ||

1495 | // might. Also, math builtins have the same semantics as their math library | 1580 | // might. Also, math builtins have the same semantics as their math library | ||

1496 | // twins. Thus, we can transform math library and builtin calls to their | 1581 | // twins. Thus, we can transform math library and builtin calls to their | ||

1497 | // LLVM counterparts if the call is marked 'const' (known to never set errno). | 1582 | // LLVM counterparts if the call is marked 'const' (known to never set errno). | ||

1498 | if (FD->hasAttr<ConstAttr>()) { | 1583 | if (FD->hasAttr<ConstAttr>()) { | ||

1499 | switch (BuiltinID) { | 1584 | switch (BuiltinID) { | ||

1500 | case Builtin::BIceil: | 1585 | case Builtin::BIceil: | ||

▲ Show 20 Lines • Show All 492 Lines • Show Last 20 Lines |

Could you move the body of this into a helper function? This function is really far too large as it is.