static folly::Optional<ArrayInfo> intersect(ArrayInfo a, ArrayInfo b) { assert(a != b); auto const aka = okind(a); auto const akb = okind(b); auto const ata = arrayType(a); auto const atb = arrayType(b); if (aka == akb) { // arrayType must be non-equal by above assertion. Since the // kinds are the same, as long as one is null we can keep the // other. assert(ata != atb); if (ata && atb) return makeArrayInfo(aka, nullptr); return makeArrayInfo(aka, ata ? ata : atb); } if (aka && akb) { assert(aka != akb); if (ata == atb) { return makeArrayInfo(folly::none, ata); } return folly::none; } assert(aka.hasValue() || akb.hasValue()); assert(!(aka.hasValue() && akb.hasValue())); if (akb && !aka) return intersect(b, a); assert(aka.hasValue() && !akb.hasValue()); if (!atb) return makeArrayInfo(aka, ata /* could be null */); if (!ata) return makeArrayInfo(aka, atb /* could be null */); return makeArrayInfo(aka, ata == atb ? ata : nullptr); }
TypePtr Parser::parseType() { if (match(TokenType::Array)) { if (!match(TokenType::LBracket)) { reportError(ErrorCodes::ExpectedLBracket); panic(typeFollow, typeFollowSize); return TypePtr(); } NumberPtr from = parseNumber(); if (m_errorCode > ErrorCodes::NoError) { panic(typeFollow, typeFollowSize); return TypePtr(); } if (!match(TokenType::Range)) { reportError(ErrorCodes::ExpectedRange); panic(typeFollow, typeFollowSize); return TypePtr(); } NumberPtr to = parseNumber(); if (m_errorCode > ErrorCodes::NoError) { panic(typeFollow, typeFollowSize); return TypePtr(); } if (!match(TokenType::RBracket)) { reportError(ErrorCodes::ExpectedRBracket); panic(typeFollow, typeFollowSize); return TypePtr(); } if (!match(TokenType::Of)) { reportError(ErrorCodes::ExpectedOf); panic(typeFollow, typeFollowSize); return TypePtr(); } TypePtr type = parseStandardType(); if (m_errorCode > ErrorCodes::NoError) { panic(typeFollow, typeFollowSize); return TypePtr(); } TypePtr arrayType(new Type); arrayType->isArray = true; arrayType->startsAt = from; arrayType->endsAt = to; arrayType->standardType = type->standardType; return arrayType; } return parseStandardType(); }
// <typ> ::= <simpletype> | <arraytype> // <simpletype> ::= <identifier of type> // <identifier of type> ::= <identifier> // <arraytype> ::= ARRAY [ <indexrange> ] OF <simpletype> void SyntaxAnalyzer::typ() { if (symbol == ident) { simpleType(); } else if (symbol == arraysy) { arrayType(); } } // typ( )
static folly::Optional<ArrayInfo> commonAncestor(ArrayInfo a, ArrayInfo b) { if (a == b) return a; auto const sameKind = [&]() -> folly::Optional<ArrayData::ArrayKind> { if (arrayKindValid(a)) { if (arrayKindValid(b)) { if (a == b) return kind(a); return folly::none; } return kind(a); } if (arrayKindValid(b)) return kind(b); return folly::none; }(); auto const ty = [&]() -> const RepoAuthType::Array* { auto ata = arrayType(a); auto atb = arrayType(b); return ata && atb ? (ata == atb ? ata : nullptr) : ata ? ata : atb; }(); if (ty || sameKind) return makeArrayInfo(sameKind, ty); return folly::none; }
Output::Output(CompilerState& state) : m_state(state) , m_repo(state.m_context, state.m_module) , m_builder(nullptr) , m_stackMapsId(1) , m_currentBlockTerminated(false) { m_argType = pointerType(arrayType(repo().intPtr, state.m_platformDesc.m_contextSize / sizeof(intptr_t))); state.m_function = addFunction( state.m_module, "main", functionType(repo().voidType, m_argType)); llvmAPI->SetFunctionCallConv(state.m_function, LLVMFastCallConv); m_builder = llvmAPI->CreateBuilderInContext(state.m_context); m_prologue = appendBasicBlock("Prologue"); positionToBBEnd(m_prologue); buildGetArg(); }
bool ComplexType::isArray() const { return !arrayType().isEmpty(); }
#include "ASTUtility.h" //StatementMatcher callExprMatcher = callExpr().bind("callexpr"); StatementMatcher mallocMatcher = callExpr(callee(functionDecl(hasName("malloc")).bind("m"))).bind("mallocCall"); StatementMatcher freeMatcher = callExpr(callee(functionDecl(hasName("free")).bind("f"))).bind("freeCall"); StatementMatcher reallocMatcher = callExpr(callee(functionDecl(hasName("realloc")).bind("r"))).bind("reallocCall"); //memcpy arrayType non-builtin = pointer or user-defined StatementMatcher memcpyAryMatcher = callExpr( callee(functionDecl(hasName("memcpy")).bind("cpy")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(arrayType( unless(hasElementType(builtinType()))).bind("cpyParm"))))))) ).bind("memcpyCall"); StatementMatcher memcpyPtrMatcher = callExpr( callee(functionDecl(hasName("memcpy")).bind("cpy")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(pointerType( pointee(unless(builtinType()))).bind("cpyParmPtr"))))))) ).bind("memcpyCall"); StatementMatcher memcmpAryMatcher = callExpr( callee(functionDecl(hasName("memcmp")).bind("cmp")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(arrayType( unless(hasElementType(builtinType()))).bind("cmpParm"))))))) ).bind("memcmpCall"); StatementMatcher memcmpPtrMatcher = callExpr( callee(functionDecl(hasName("memcmp")).bind("cmp")), hasAnyArgument(ignoringImpCasts(declRefExpr(
static bool subtypeOf(ArrayInfo a, ArrayInfo b) { if (a == b) return true; if (!arrayType(b) && !arrayKindValid(b)) return true; return false; }
bool SkMemberInfo::setValue(SkAnimateMaker& maker, SkTDOperandArray* arrayStorage, int storageOffset, int maxStorage, SkDisplayable* displayable, SkDisplayTypes outType, const char rawValue[], size_t rawValueLen) const { SkString valueStr(rawValue, rawValueLen); SkScriptValue scriptValue; scriptValue.fType = SkType_Unknown; scriptValue.fOperand.fS32 = 0; SkDisplayTypes type = getType(); SkAnimatorScript engine(maker, displayable, type); if (arrayStorage) displayable = NULL; bool success = true; void* untypedStorage = NULL; if (displayable && fType != SkType_MemberProperty && fType != SkType_MemberFunction) untypedStorage = (SkTDOperandArray*) memberData(displayable); if (type == SkType_ARGB) { // for both SpiderMonkey and SkiaScript, substitute any #xyz or #xxyyzz first // it's enough to expand the colors into 0xFFxxyyzz const char* poundPos; while ((poundPos = strchr(valueStr.c_str(), '#')) != NULL) { size_t offset = poundPos - valueStr.c_str(); if (valueStr.size() - offset < 4) break; char r = poundPos[1]; char g = poundPos[2]; char b = poundPos[3]; if (is_hex(r) == false || is_hex(g) == false || is_hex(b) == false) break; char hex = poundPos[4]; if (is_hex(hex) == false) { valueStr.insertUnichar(offset + 1, r); valueStr.insertUnichar(offset + 3, g); valueStr.insertUnichar(offset + 5, b); } *(char*) poundPos = '0'; // overwrite '#' valueStr.insert(offset + 1, "xFF"); } } if (SkDisplayType::IsDisplayable(&maker, type) || SkDisplayType::IsEnum(&maker, type) || type == SkType_ARGB) goto scriptCommon; switch (type) { case SkType_String: #if 0 if (displayable && displayable->isAnimate()) { goto noScriptString; } if (strncmp(rawValue, "#string:", sizeof("#string:") - 1) == 0) { SkASSERT(sizeof("string") == sizeof("script")); char* stringHeader = valueStr.writable_str(); memcpy(&stringHeader[1], "script", sizeof("script") - 1); rawValue = valueStr.c_str(); goto noScriptString; } else #endif if (strncmp(rawValue, "#script:", sizeof("#script:") - 1) != 0) goto noScriptString; valueStr.remove(0, 8); case SkType_Unknown: case SkType_Int: case SkType_MSec: // for the purposes of script, MSec is treated as a Scalar case SkType_Point: case SkType_3D_Point: case SkType_Float: case SkType_Array: scriptCommon: { const char* script = valueStr.c_str(); success = engine.evaluateScript(&script, &scriptValue); if (success == false) { maker.setScriptError(engine); return false; } } SkASSERT(success); if (scriptValue.fType == SkType_Displayable) { if (type == SkType_String) { const char* charPtr; maker.findKey(scriptValue.fOperand.fDisplayable, &charPtr); scriptValue.fOperand.fString = new SkString(charPtr); scriptValue.fType = SkType_String; engine.SkScriptEngine::track(scriptValue.fOperand.fString); break; } SkASSERT(SkDisplayType::IsDisplayable(&maker, type)); if (displayable) displayable->setReference(this, scriptValue.fOperand.fDisplayable); else arrayStorage->begin()[0].fDisplayable = scriptValue.fOperand.fDisplayable; return true; } if (type != scriptValue.fType) { if (scriptValue.fType == SkType_Array) { engine.forget(scriptValue.getArray()); goto writeStruct; // real structs have already been written by script } switch (type) { case SkType_String: success = engine.convertTo(SkType_String, &scriptValue); break; case SkType_MSec: case SkType_Float: success = engine.convertTo(SkType_Float, &scriptValue); break; case SkType_Int: success = engine.convertTo(SkType_Int, &scriptValue); break; case SkType_Array: success = engine.convertTo(arrayType(), &scriptValue); // !!! incomplete; create array of appropriate type and add scriptValue to it SkASSERT(0); break; case SkType_Displayable: case SkType_Drawable: return false; // no way to convert other types to this default: // to avoid warnings break; } if (success == false) return false; } if (type == SkType_MSec) scriptValue.fOperand.fMSec = SkScalarMulRound(scriptValue.fOperand.fScalar, 1000); scriptValue.fType = type; break; noScriptString: case SkType_DynamicString: if (fType == SkType_MemberProperty && displayable) { SkString string(rawValue, rawValueLen); SkScriptValue scriptValue; scriptValue.fOperand.fString = &string; scriptValue.fType = SkType_String; displayable->setProperty(propertyIndex(), scriptValue); } else if (displayable) { SkString* string = (SkString*) memberData(displayable); string->set(rawValue, rawValueLen); } else { SkASSERT(arrayStorage->count() == 1); arrayStorage->begin()->fString->set(rawValue, rawValueLen); } goto dirty; case SkType_Base64: { SkBase64 base64; base64.decode(rawValue, rawValueLen); *(SkBase64* ) untypedStorage = base64; } goto dirty; default: SkASSERT(0); break; } // if (SkDisplayType::IsStruct(type) == false) { writeStruct: if (writeValue(displayable, arrayStorage, storageOffset, maxStorage, untypedStorage, outType, scriptValue)) { maker.setErrorCode(SkDisplayXMLParserError::kUnexpectedType); return false; } } dirty: if (displayable) displayable->dirty(); return true; }