1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ECMASCRIPT_COMPILER_CALL_SIGNATURE_H
17#define ECMASCRIPT_COMPILER_CALL_SIGNATURE_H
18
19#include <array>
20#include <functional>
21#include <memory>
22
23#include "ecmascript/compiler/variable_type.h"
24
25#include "libpandabase/macros.h"
26#include "libpandabase/utils/bit_field.h"
27
28namespace panda::ecmascript::kungfu {
29class Circuit;
30
31enum class ArgumentsOrder {
32    DEFAULT_ORDER,  // Push Arguments in stack from right -> left
33};
34
35class CallSignature {
36public:
37    using TargetConstructor = std::function<void *(void *)>;
38    enum class TargetKind : uint8_t {
39        COMMON_STUB = 0,
40        RUNTIME_STUB,
41        RUNTIME_STUB_VARARGS,
42        RUNTIME_STUB_NO_GC,
43        ASM_CALL_BARRIER_STUB,
44        OPTIMIZED_STUB,
45        OPTIMIZED_FAST_CALL_STUB,
46        DEOPT_STUB,
47        BYTECODE_HANDLER,
48        BYTECODE_DEBUGGER_HANDLER,
49        BYTECODE_HELPER_HANDLER,
50        BYTECODE_PROFILE_HANDLER,
51        BYTECODE_JIT_PROFILE_HANDLER,
52        JSFUNCTION,
53        BUILTINS_STUB,
54        BUILTINS_WITH_ARGV_STUB,
55        BASELINE_STUB,
56
57        STUB_BEGIN = COMMON_STUB,
58        STUB_END = BYTECODE_HANDLER,
59        BCHANDLER_BEGIN = BYTECODE_HANDLER,
60        BCHANDLER_END = JSFUNCTION
61    };
62    enum class CallConv: uint8_t {
63        CCallConv = 0,
64        GHCCallConv = 1,
65        WebKitJSCallConv = 2,
66    };
67    // ParamAttr only works for LLVM backend.
68    enum class ParamAttr: uint8_t {
69        NoAttr = 0,
70        Dead
71    };
72    static constexpr size_t TARGET_KIND_BIT_LENGTH = 5;
73    static constexpr size_t CALL_CONV_BIT_LENGTH = 2;
74    using TargetKindBit = panda::BitField<TargetKind, 0, TARGET_KIND_BIT_LENGTH>;
75    using CallConvBit = TargetKindBit::NextField<CallConv, CALL_CONV_BIT_LENGTH>;
76    using VariadicArgsBit = CallConvBit::NextField<bool, 1>;
77    using TailCallBit = VariadicArgsBit::NextField<bool, 1>;
78    using GCLeafFunctionBit = TailCallBit::NextField<bool, 1>;
79
80    CallSignature(std::string name, int flags, size_t paramCounter, ArgumentsOrder order,
81                  VariableType returnType)
82        : name_(name), paramCounter_(paramCounter), order_(order), returnType_(returnType)
83    {
84        SetTargetKind(TargetKind::COMMON_STUB);
85        SetCallConv(CallSignature::CallConv::CCallConv);
86        SetTailCall(false);
87        SetGCLeafFunction(false);
88        SetVariadicArgs(flags);
89    }
90
91    CallSignature(std::string name, int flags, ArgumentsOrder order, VariableType returnType,
92                  std::initializer_list<VariableType> params)
93        : CallSignature(std::move(name), flags, params.size(), order, returnType)
94    {
95        paramsType_ = std::make_unique<std::vector<VariableType>>(params);
96    }
97
98    CallSignature() = default;
99
100    ~CallSignature() = default;
101
102    CallSignature(CallSignature const &other)
103    {
104        name_ = other.name_;
105        paramCounter_ = other.paramCounter_;
106        order_ = other.order_;
107        id_ = other.id_;
108        returnType_ = other.returnType_;
109        constructor_ = other.constructor_;
110        if (paramCounter_ > 0 && other.paramsType_ != nullptr) {
111            paramsType_ = std::make_unique<std::vector<VariableType>>(paramCounter_);
112            for (size_t i = 0; i < paramCounter_; i++) {
113                (*paramsType_)[i] = other.GetParametersType()[i];
114            }
115        }
116        kind_ = other.kind_;
117    }
118
119    CallSignature &operator=(CallSignature const &other)
120    {
121        name_ = other.name_;
122        paramCounter_ = other.paramCounter_;
123        order_ = other.order_;
124        id_ = other.id_;
125        returnType_ = other.returnType_;
126        constructor_ = other.constructor_;
127        if (paramCounter_ > 0 && other.paramsType_ != nullptr) {
128            paramsType_ = std::make_unique<std::vector<VariableType>>(paramCounter_);
129            for (size_t i = 0; i < paramCounter_; i++) {
130                (*paramsType_)[i] = other.GetParametersType()[i];
131            }
132        }
133        kind_ = other.kind_;
134        return *this;
135    }
136
137    bool IsCommonStub() const
138    {
139        return (GetTargetKind() == TargetKind::COMMON_STUB);
140    }
141
142    bool IsRuntimeVAStub() const
143    {
144        return (GetTargetKind() == TargetKind::RUNTIME_STUB_VARARGS);
145    }
146
147    bool IsRuntimeStub() const
148    {
149        return (GetTargetKind() == TargetKind::RUNTIME_STUB);
150    }
151
152    bool IsASMCallBarrierStub() const
153    {
154        return (GetTargetKind() == TargetKind::ASM_CALL_BARRIER_STUB);
155    }
156
157    bool IsRuntimeNGCStub() const
158    {
159        return (GetTargetKind() == TargetKind::RUNTIME_STUB_NO_GC);
160    }
161
162    bool IsOptimizedStub() const
163    {
164        return (GetTargetKind() == TargetKind::OPTIMIZED_STUB);
165    }
166
167    bool IsOptimizedFastCallStub() const
168    {
169        return (GetTargetKind() == TargetKind::OPTIMIZED_FAST_CALL_STUB);
170    }
171
172    bool IsBCDebuggerStub() const
173    {
174        return (GetTargetKind() == TargetKind::BYTECODE_DEBUGGER_HANDLER);
175    }
176
177    bool IsStub() const
178    {
179        TargetKind targetKind = GetTargetKind();
180        return TargetKind::STUB_BEGIN <= targetKind && targetKind < TargetKind::STUB_END;
181    }
182
183    bool IsBCStub() const
184    {
185        TargetKind targetKind = GetTargetKind();
186        return TargetKind::BCHANDLER_BEGIN <= targetKind && targetKind < TargetKind::BCHANDLER_END;
187    }
188
189    bool IsBuiltinsStub() const
190    {
191        return (GetTargetKind() == TargetKind::BUILTINS_STUB);
192    }
193
194    bool IsBuiltinsWithArgvStub() const
195    {
196        return (GetTargetKind() == TargetKind::BUILTINS_WITH_ARGV_STUB);
197    }
198
199    bool IsBCHandlerStub() const
200    {
201        return (GetTargetKind() == TargetKind::BYTECODE_HANDLER);
202    }
203
204    bool IsDeoptStub() const
205    {
206        return (GetTargetKind() == TargetKind::DEOPT_STUB);
207    }
208
209    bool IsBaselineStub() const
210    {
211        return (GetTargetKind() == TargetKind::BASELINE_STUB);
212    }
213
214    void SetParameters(VariableType *paramsType)
215    {
216        if (paramCounter_ > 0 && paramsType_ == nullptr) {
217            paramsType_ = std::make_unique<std::vector<VariableType>>(paramCounter_);
218            for (size_t i = 0; i < paramCounter_; i++) {
219                (*paramsType_)[i] = paramsType[i];
220            }
221        }
222    }
223
224    VariableType *GetParametersType() const
225    {
226        if (paramsType_ != nullptr) {
227            return paramsType_->data();
228        } else {
229            return nullptr;
230        }
231    }
232
233    void SetParamAttr(std::vector<ParamAttr> &&paramAttr)
234    {
235        if (paramCounter_ > 0 && paramsAttr_ == nullptr) {
236            paramsAttr_ = std::make_unique<std::vector<ParamAttr>>(paramAttr);
237        }
238    }
239
240    std::vector<ParamAttr> *GetParamAttr() const
241    {
242        if (paramsAttr_ != nullptr) {
243            return paramsAttr_.get();
244        } else {
245            return nullptr;
246        }
247    }
248
249    size_t GetParametersCount() const
250    {
251        return paramCounter_;
252    }
253
254    VariableType GetReturnType() const
255    {
256        return returnType_;
257    }
258
259    ArgumentsOrder GetArgumentsOrder() const
260    {
261        return order_;
262    }
263
264    bool IsVariadicArgs() const
265    {
266        return VariadicArgsBit::Decode(kind_);
267    }
268
269    void SetVariadicArgs(bool variable)
270    {
271        VariadicArgsBit::Set<uint64_t>(variable, &kind_);
272    }
273
274    void SetTailCall(bool tailCall)
275    {
276        TailCallBit::Set<uint64_t>(tailCall, &kind_);
277    }
278
279    bool GetTailCall() const
280    {
281        return TailCallBit::Decode(kind_);
282    }
283
284    void SetGCLeafFunction(bool value)
285    {
286        GCLeafFunctionBit::Set<uint64_t>(value, &kind_);
287    }
288
289    bool GetGCLeafFunction() const
290    {
291        return GCLeafFunctionBit::Decode(kind_);
292    }
293
294    TargetKind GetTargetKind() const
295    {
296        return TargetKindBit::Decode(kind_);
297    }
298
299    void SetTargetKind(TargetKind kind)
300    {
301        TargetKindBit::Set<uint64_t>(kind, &kind_);
302    }
303
304    CallConv GetCallConv() const
305    {
306        return CallConvBit::Decode(kind_);
307    }
308
309    void SetCallConv(CallConv cc)
310    {
311        CallConvBit::Set<uint64_t>(cc, &kind_);
312    }
313
314    const std::string &GetName() const
315    {
316        return name_;
317    }
318
319    void SetName(const std::string &str)
320    {
321        name_ = str;
322    }
323
324    void SetConstructor(TargetConstructor ctor)
325    {
326        constructor_ = ctor;
327    }
328
329    TargetConstructor GetConstructor() const
330    {
331        return constructor_;
332    }
333
334    bool HasConstructor() const
335    {
336        return constructor_ != nullptr;
337    }
338
339    int GetID() const
340    {
341        return id_;
342    }
343
344    void SetID(int id)
345    {
346        id_ = id;
347    }
348
349private:
350    std::string name_;
351    size_t paramCounter_ {0};
352    int id_ {-1};
353    ArgumentsOrder order_ {ArgumentsOrder::DEFAULT_ORDER};
354    VariableType returnType_ {VariableType::VOID()};
355    std::unique_ptr<std::vector<VariableType>> paramsType_ {nullptr};
356    std::unique_ptr<std::vector<ParamAttr>> paramsAttr_ {nullptr};
357    TargetConstructor constructor_ {nullptr};
358    uint64_t kind_ {0};
359};
360
361#define EXPLICIT_CALL_SIGNATURE_LIST(V)         \
362    V(Add)                                      \
363    V(Sub)                                      \
364    V(Mul)                                      \
365    V(MulGCTest)                                \
366    V(Div)                                      \
367    V(Mod)                                      \
368    V(TypeOf)                                   \
369    V(Equal)                                    \
370    V(NotEqual)                                 \
371    V(StrictEqual)                              \
372    V(StrictNotEqual)                           \
373    V(Less)                                     \
374    V(LessEq)                                   \
375    V(Greater)                                  \
376    V(GreaterEq)                                \
377    V(Shl)                                      \
378    V(Shr)                                      \
379    V(Ashr)                                     \
380    V(And)                                      \
381    V(Or)                                       \
382    V(Xor)                                      \
383    V(Instanceof)                               \
384    V(Inc)                                      \
385    V(Dec)                                      \
386    V(Neg)                                      \
387    V(Not)                                      \
388    V(ToBooleanTrue)                            \
389    V(ToBooleanFalse)                           \
390    V(SetPropertyByName)                        \
391    V(DeprecatedSetPropertyByName)              \
392    V(SetPropertyByNameWithOwn)                 \
393    V(SetPropertyByValue)                       \
394    V(DeprecatedSetPropertyByValue)             \
395    V(TryLdGlobalByName)                        \
396    V(TryStGlobalByName)                        \
397    V(LdGlobalVar)                              \
398    V(StGlobalVar)                              \
399    V(StOwnByIndex)                             \
400    V(StOwnByValue)                             \
401    V(StOwnByName)                              \
402    V(StOwnByValueWithNameSet)                  \
403    V(StOwnByNameWithNameSet)                   \
404    V(StObjByIndex)                             \
405    V(LdObjByIndex)                             \
406    V(SetPropertyByValueWithOwn)                \
407    V(GetPropertyByName)                        \
408    V(DeprecatedGetPropertyByName)              \
409    V(GetPropertyByIndex)                       \
410    V(SetPropertyByIndex)                       \
411    V(SetPropertyByIndexWithOwn)                \
412    V(GetPropertyByValue)                       \
413    V(DeprecatedGetPropertyByValue)             \
414    V(TryLoadICByName)                          \
415    V(TryLoadICByValue)                         \
416    V(TryStoreICByName)                         \
417    V(TryStoreICByValue)                        \
418    V(SetValueWithBarrier)                      \
419    V(SetNonSValueWithBarrier)                  \
420    V(SetValueWithEdenBarrier)                  \
421    V(SetNonSValueWithEdenBarrier)              \
422    V(SetSValueWithBarrier)                     \
423    V(NewLexicalEnv)                            \
424    V(CopyRestArgs)                             \
425    V(GetUnmappedArgs)                          \
426    V(GetCallSpreadArgs)                        \
427    V(NewThisObjectChecked)                     \
428    V(ConstructorCheck)                         \
429    V(CreateEmptyArray)                         \
430    V(CreateArrayWithBuffer)                    \
431    V(NewJSObject)                              \
432    V(GetTaggedArrayPtrTest)                    \
433    V(BytecodeHandler)                          \
434    V(Builtins)                                 \
435    V(BuiltinsWithArgv)                         \
436    V(BytecodeDebuggerHandler)                  \
437    V(CallRuntime)                              \
438    V(AsmInterpreterEntry)                      \
439    V(CallArg0AndCheckToBaseline)               \
440    V(CallArg1AndCheckToBaseline)               \
441    V(CallArgs2AndCheckToBaseline)              \
442    V(CallArgs3AndCheckToBaseline)              \
443    V(CallThisArg0AndCheckToBaseline)           \
444    V(CallThisArg1AndCheckToBaseline)           \
445    V(CallThisArgs2AndCheckToBaseline)          \
446    V(CallThisArgs3AndCheckToBaseline)          \
447    V(CallRangeAndCheckToBaseline)              \
448    V(CallNewAndCheckToBaseline)                \
449    V(SuperCallAndCheckToBaseline)              \
450    V(CallThisRangeAndCheckToBaseline)          \
451    V(GeneratorReEnterAsmInterp)                \
452    V(CallRuntimeWithArgv)                      \
453    V(OptimizedCallAndPushArgv)                 \
454    V(OptimizedFastCallAndPushArgv)             \
455    V(AOTCallToAsmInterBridge)                  \
456    V(FastCallToAsmInterBridge)                 \
457    V(PushCallArg0AndDispatch)                  \
458    V(PushCallArgsAndDispatchNative)            \
459    V(PushCallArg1AndDispatch)                  \
460    V(PushCallArgs2AndDispatch)                 \
461    V(PushCallArgs3AndDispatch)                 \
462    V(PushCallRangeAndDispatch)                 \
463    V(PushCallRangeAndDispatchNative)           \
464    V(PushCallThisRangeAndDispatch)             \
465    V(PushCallThisArg0AndDispatch)              \
466    V(PushCallThisArg1AndDispatch)              \
467    V(PushCallThisArgs2AndDispatch)             \
468    V(PushCallThisArgs3AndDispatch)             \
469    V(PushCallNewAndDispatchNative)             \
470    V(PushNewTargetAndDispatchNative)           \
471    V(PushCallNewAndDispatch)                   \
472    V(PushSuperCallAndDispatch)                 \
473    V(CallGetter)                               \
474    V(CallSetter)                               \
475    V(CallContainersArgs2)                      \
476    V(CallContainersArgs3)                      \
477    V(JSCallWithArgV)                           \
478    V(JSFastCallWithArgV)                       \
479    V(JSFastCallWithArgVAndPushArgv)            \
480    V(JSCallWithArgVAndPushArgv)                \
481    V(SuperCallWithArgV)                        \
482    V(ResumeRspAndDispatch)                     \
483    V(ResumeRspAndReturn)                       \
484    V(ResumeRspAndReturnBaseline)               \
485    V(ResumeCaughtFrameAndDispatch)             \
486    V(ResumeUncaughtFrameAndReturn)             \
487    V(ResumeRspAndRollback)                     \
488    V(StringsAreEquals)                         \
489    V(BigIntEquals)                             \
490    V(BigIntSameValueZero)                      \
491    V(CallBigIntAsIntN)                         \
492    V(CallBigIntAsUintN)                        \
493    V(Dump)                                     \
494    V(DebugDump)                                \
495    V(DumpWithHint)                             \
496    V(DebugDumpWithHint)                        \
497    V(DebugPrint)                               \
498    V(DebugPrintCustom)                         \
499    V(DebugPrintInstruction)                    \
500    V(DebugOsrEntry)                            \
501    V(Comment)                                  \
502    V(FatalPrint)                               \
503    V(FatalPrintCustom)                         \
504    V(GetActualArgvNoGC)                        \
505    V(InsertNewToEdenRSet)                      \
506    V(InsertOldToNewRSet)                       \
507    V(InsertLocalToShareRSet)                   \
508    V(SetBitAtomic)                             \
509    V(DoubleToInt)                              \
510    V(DoubleToLength)                           \
511    V(FloatMod)                                 \
512    V(FloatAcos)                                \
513    V(FloatAcosh)                               \
514    V(FloatAsin)                                \
515    V(FloatAsinh)                               \
516    V(FloatAtan)                                \
517    V(FloatAtan2)                               \
518    V(FloatAtanh)                               \
519    V(FloatCos)                                 \
520    V(FloatCosh)                                \
521    V(FloatSin)                                 \
522    V(FloatSinh)                                \
523    V(FloatTan)                                 \
524    V(FloatTanh)                                \
525    V(FloatTrunc)                               \
526    V(FloatLog)                                 \
527    V(FloatLog2)                                \
528    V(FloatLog10)                               \
529    V(FloatLog1p)                               \
530    V(FloatExp)                                 \
531    V(FloatExpm1)                               \
532    V(FloatCbrt)                                \
533    V(FloatClz32)                               \
534    V(FloatFloor)                               \
535    V(FloatPow)                                 \
536    V(FloatCeil)                                \
537    V(CallDateNow)                              \
538    V(NumberIsFinite)                           \
539    V(FindElementWithCache)                     \
540    V(UpdateFieldType)                          \
541    V(MarkingBarrier)                           \
542    V(MarkingBarrierWithEden)                   \
543    V(SharedGCMarkingBarrier)                   \
544    V(StoreBarrier)                             \
545    V(CallArg0)                                 \
546    V(CallArg1)                                 \
547    V(CallArgs2)                                \
548    V(CallArgs3)                                \
549    V(CallThisRange)                            \
550    V(CallRange)                                \
551    V(JSCall)                                   \
552    V(JSOptimizedCall)                          \
553    V(JSOptimizedFastCall)                      \
554    V(JSFunctionEntry)                          \
555    V(OptimizedFastCallEntry)                   \
556    V(JSProxyCallInternalWithArgV)              \
557    V(CreateArrayFromList)                      \
558    V(JSObjectGetMethod)                        \
559    V(JsProxyCallInternal)                      \
560    V(JsBoundCallInternal)                      \
561    V(DeoptHandlerAsm)                          \
562    V(JSCallNew)                                \
563    V(CallOptimized)                            \
564    V(TimeClip)                                 \
565    V(SetDateValues)                            \
566    V(CallReturnWithArgv)                       \
567    V(StartCallTimer)                           \
568    V(EndCallTimer)                             \
569    V(GetSingleCharCodeByIndex)                 \
570    V(CreateStringBySingleCharCode)             \
571    V(FastStringEqual)                          \
572    V(FastStringAdd)                            \
573    V(DeleteObjectProperty)                     \
574    V(Getpropiterator)                          \
575    V(Getnextpropname)                          \
576    V(CreateJSSetIterator)                      \
577    V(CreateJSMapIterator)                      \
578    V(JSMapGet)                                 \
579    V(JSMapHas)                                 \
580    V(JSMapKeys)                                \
581    V(JSMapValues)                              \
582    V(JSSetHas)                                 \
583    V(JSSetAdd)                                 \
584    V(JSMapDelete)                              \
585    V(JSSetDelete)                              \
586    V(CreateJSTypedArrayEntries)                \
587    V(CreateJSTypedArrayKeys)                   \
588    V(CreateJSTypedArrayValues)                 \
589    V(JSSetEntries)                             \
590    V(JSHClassFindProtoTransitions)             \
591    V(NumberHelperStringToDouble)               \
592    V(GetStringToListCacheArray)                \
593    V(FastArraySort)                            \
594    V(FastArraySortString)                      \
595    V(StringToNumber)                           \
596    V(StringGetStart)                           \
597    V(StringGetEnd)                             \
598    V(ArrayTrim)                                \
599    V(OptimizedFastJmp)                         \
600    V(CopyTypedArrayBuffer)                     \
601    V(CallArg0AndDispatchFromBaseline)          \
602    V(CallArg1AndDispatchFromBaseline)          \
603    V(CallArgs2AndDispatchFromBaseline)         \
604    V(CallArgs3AndDispatchFromBaseline)         \
605    V(CallThisArg0AndDispatchFromBaseline)      \
606    V(CallThisArg1AndDispatchFromBaseline)      \
607    V(CallThisArgs2AndDispatchFromBaseline)     \
608    V(CallThisArgs3AndDispatchFromBaseline)     \
609    V(CallRangeAndDispatchFromBaseline)         \
610    V(CallNewAndDispatchFromBaseline)           \
611    V(SuperCallAndDispatchFromBaseline)         \
612    V(CallThisRangeAndDispatchFromBaseline)     \
613    V(CallArg0AndCheckToBaselineFromBaseline)        \
614    V(CallArg1AndCheckToBaselineFromBaseline)        \
615    V(CallArgs2AndCheckToBaselineFromBaseline)       \
616    V(CallArgs3AndCheckToBaselineFromBaseline)       \
617    V(CallThisArg0AndCheckToBaselineFromBaseline)    \
618    V(CallThisArg1AndCheckToBaselineFromBaseline)    \
619    V(CallThisArgs2AndCheckToBaselineFromBaseline)   \
620    V(CallThisArgs3AndCheckToBaselineFromBaseline)   \
621    V(CallRangeAndCheckToBaselineFromBaseline)       \
622    V(CallNewAndCheckToBaselineFromBaseline)         \
623    V(SuperCallAndCheckToBaselineFromBaseline)       \
624    V(CallThisRangeAndCheckToBaselineFromBaseline)   \
625    V(SameValue)                                     \
626    V(GetBaselineBuiltinFp)                          \
627    V(StringIteratorNext)                            \
628    V(Definefunc)                                    \
629    V(DefineField)                                   \
630    V(ConvertCharToInt32)                            \
631    V(ConvertCharToDouble)                           \
632    V(ASMFastWriteBarrier)                           \
633    V(ASMWriteBarrierWithEden)                       \
634    V(VerifyBarrier)                                 \
635    V(IsFastRegExp)
636
637#define DECL_CALL_SIGNATURE(name)                                  \
638class name##CallSignature final {                                  \
639    public:                                                        \
640        static void Initialize(CallSignature *descriptor);         \
641    };
642EXPLICIT_CALL_SIGNATURE_LIST(DECL_CALL_SIGNATURE)
643
644// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
645#define DEF_CALL_SIGNATURE(name)                                  \
646    void name##CallSignature::Initialize([[maybe_unused]] CallSignature *callSign)
647}  // namespace panda::ecmascript::kungfu
648#endif  // ECMASCRIPT_COMPILER_CALL_SIGNATURE_H
649