Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/sksl/ir/SkSLVarDeclarations.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2021 Google LLC
3
 *
4
 * Use of this source code is governed by a BSD-style license that can be
5
 * found in the LICENSE file.
6
 */
7
8
#include "src/sksl/SkSLAnalysis.h"
9
#include "src/sksl/SkSLContext.h"
10
#include "src/sksl/SkSLProgramSettings.h"
11
#include "src/sksl/ir/SkSLVarDeclarations.h"
12
13
namespace SkSL {
14
15
0
std::unique_ptr<Statement> VarDeclaration::clone() const {
16
0
    return std::make_unique<VarDeclaration>(&this->var(),
17
0
                                            &this->baseType(),
18
0
                                            fArraySize,
19
0
                                            this->value() ? this->value()->clone() : nullptr);
20
0
}
21
22
0
String VarDeclaration::description() const {
23
0
    String result = this->var().modifiers().description() + this->baseType().description() + " " +
24
0
                    this->var().name();
25
0
    if (this->arraySize() > 0) {
26
0
        result.appendf("[%d]", this->arraySize());
27
0
    } else if (this->arraySize() == Type::kUnsizedArray) {
28
0
        result += "[]";
29
0
    }
30
0
    if (this->value()) {
31
0
        result += " = " + this->value()->description();
32
0
    }
33
0
    result += ";";
34
0
    return result;
35
0
}
36
37
std::unique_ptr<Statement> VarDeclaration::Convert(const Context& context,
38
                                                   Variable* var,
39
542k
                                                   std::unique_ptr<Expression> value) {
40
542k
    if (var->modifiers().fFlags & Modifiers::kConst_Flag) {
41
3.47k
        if (!value) {
42
1.64k
            context.errors().error(var->fOffset, "'const' variables must be initialized");
43
1.64k
            return nullptr;
44
1.64k
        }
45
1.82k
        if (!Analysis::IsConstantExpression(*value)) {
46
714
            context.errors().error(value->fOffset,
47
714
                                   "'const' variable initializer must be a constant expression");
48
714
            return nullptr;
49
714
        }
50
540k
    }
51
540k
    if (value) {
52
82.2k
        if (var->storage() == Variable::Storage::kGlobal &&
53
51.9k
            !Analysis::IsConstantExpression(*value)) {
54
29.8k
            context.errors().error(value->fOffset,
55
29.8k
                                   "global variable initializer must be a constant expression");
56
29.8k
            return nullptr;
57
29.8k
        }
58
52.4k
        if (var->type().isOpaque()) {
59
1.60k
            context.errors().error(
60
1.60k
                    value->fOffset,
61
1.60k
                    "opaque type '" + var->type().name() + "' cannot use initializer expressions");
62
1.60k
            return nullptr;
63
1.60k
        }
64
50.8k
        if (var->modifiers().fFlags & Modifiers::kIn_Flag) {
65
430
            context.errors().error(value->fOffset,
66
430
                                   "'in' variables cannot use initializer expressions");
67
430
            return nullptr;
68
430
        }
69
50.3k
        if (var->modifiers().fFlags & Modifiers::kUniform_Flag) {
70
149
            context.errors().error(value->fOffset,
71
149
                                   "'uniform' variables cannot use initializer expressions");
72
149
            return nullptr;
73
149
        }
74
50.2k
        value = var->type().coerceExpression(std::move(value), context);
75
50.2k
        if (!value) {
76
13.5k
            return nullptr;
77
13.5k
        }
78
494k
    }
79
494k
    const Type* baseType = &var->type();
80
494k
    int arraySize = 0;
81
494k
    if (baseType->isArray()) {
82
22.1k
        arraySize = baseType->columns();
83
22.1k
        baseType = &baseType->componentType();
84
22.1k
    }
85
494k
    return VarDeclaration::Make(context, var, baseType, arraySize, std::move(value));
86
494k
}
87
88
std::unique_ptr<Statement> VarDeclaration::Make(const Context& context,
89
                                                Variable* var,
90
                                                const Type* baseType,
91
                                                int arraySize,
92
1.70M
                                                std::unique_ptr<Expression> value) {
93
1.70M
    SkASSERT(!baseType->isArray());
94
    // 'const' variables must be initialized
95
1.70M
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) || value);
96
    // 'const' variable initializer must be a constant expression
97
1.70M
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) ||
98
1.70M
             Analysis::IsConstantExpression(*value));
99
    // global variable initializer must be a constant expression
100
1.70M
    SkASSERT(!(value && var->storage() == Variable::Storage::kGlobal &&
101
1.70M
               !Analysis::IsConstantExpression(*value)));
102
    // opaque type cannot use initializer expressions
103
1.70M
    SkASSERT(!(value && var->type().isOpaque()));
104
    // 'in' variables cannot use initializer expressions
105
1.70M
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kIn_Flag)));
106
    // 'uniform' variables cannot use initializer expressions
107
1.70M
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kUniform_Flag)));
108
109
    // Detect and report out-of-range initial-values for this variable.
110
1.70M
    if (value) {
111
932k
        var->type().checkForOutOfRangeLiteral(context, *value);
112
932k
    }
113
114
1.70M
    auto result = std::make_unique<VarDeclaration>(var, baseType, arraySize, std::move(value));
115
1.70M
    var->setDeclaration(result.get());
116
1.70M
    return std::move(result);
117
1.70M
}
SkSL::VarDeclaration::Make(SkSL::Context const&, SkSL::Variable*, SkSL::Type const*, int, std::__1::unique_ptr<SkSL::Expression, std::__1::default_delete<SkSL::Expression> >)
Line
Count
Source
92
305
                                                std::unique_ptr<Expression> value) {
93
305
    SkASSERT(!baseType->isArray());
94
    // 'const' variables must be initialized
95
305
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) || value);
96
    // 'const' variable initializer must be a constant expression
97
305
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) ||
98
305
             Analysis::IsConstantExpression(*value));
99
    // global variable initializer must be a constant expression
100
305
    SkASSERT(!(value && var->storage() == Variable::Storage::kGlobal &&
101
305
               !Analysis::IsConstantExpression(*value)));
102
    // opaque type cannot use initializer expressions
103
305
    SkASSERT(!(value && var->type().isOpaque()));
104
    // 'in' variables cannot use initializer expressions
105
305
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kIn_Flag)));
106
    // 'uniform' variables cannot use initializer expressions
107
305
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kUniform_Flag)));
108
109
    // Detect and report out-of-range initial-values for this variable.
110
305
    if (value) {
111
117
        var->type().checkForOutOfRangeLiteral(context, *value);
112
117
    }
113
114
305
    auto result = std::make_unique<VarDeclaration>(var, baseType, arraySize, std::move(value));
115
305
    var->setDeclaration(result.get());
116
305
    return std::move(result);
117
305
}
SkSL::VarDeclaration::Make(SkSL::Context const&, SkSL::Variable*, SkSL::Type const*, int, std::__1::unique_ptr<SkSL::Expression, std::__1::default_delete<SkSL::Expression> >)
Line
Count
Source
92
1.70M
                                                std::unique_ptr<Expression> value) {
93
1.70M
    SkASSERT(!baseType->isArray());
94
    // 'const' variables must be initialized
95
1.70M
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) || value);
96
    // 'const' variable initializer must be a constant expression
97
1.70M
    SkASSERT(!(var->modifiers().fFlags & Modifiers::kConst_Flag) ||
98
1.70M
             Analysis::IsConstantExpression(*value));
99
    // global variable initializer must be a constant expression
100
1.70M
    SkASSERT(!(value && var->storage() == Variable::Storage::kGlobal &&
101
1.70M
               !Analysis::IsConstantExpression(*value)));
102
    // opaque type cannot use initializer expressions
103
1.70M
    SkASSERT(!(value && var->type().isOpaque()));
104
    // 'in' variables cannot use initializer expressions
105
1.70M
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kIn_Flag)));
106
    // 'uniform' variables cannot use initializer expressions
107
1.70M
    SkASSERT(!(value && (var->modifiers().fFlags & Modifiers::kUniform_Flag)));
108
109
    // Detect and report out-of-range initial-values for this variable.
110
1.70M
    if (value) {
111
932k
        var->type().checkForOutOfRangeLiteral(context, *value);
112
932k
    }
113
114
1.70M
    auto result = std::make_unique<VarDeclaration>(var, baseType, arraySize, std::move(value));
115
1.70M
    var->setDeclaration(result.get());
116
1.70M
    return std::move(result);
117
1.70M
}
118
119
}  // namespace SkSL