static void CheckInitializer(AstInitializer init, Type ty) { int offset = 0, error = 0; struct initData header; InitData tail = &header; InitData prev, curr; header.next = NULL; if (IsScalarType(ty) && init->lbrace) { init = (AstInitializer)init->initials; } else if (ty->categ == ARRAY && ! (ty->bty->categ == CHAR || ty->bty->categ == UCHAR)) { if (! init->lbrace) { Error(&init->coord, "Can't initialize array without brace"); return; } } else if ((ty->categ == STRUCT || ty->categ == UNION) && ! init->lbrace) { init->expr = Adjust(CheckExpression(init->expr), 1); if (! CanAssign(ty, init->expr)) { Error(&init->coord, "Wrong initializer"); } else { ALLOC(init->idata); init->idata->expr = init->expr; init->idata->offset = 0; init->idata->next = NULL; } return; } CheckInitializerInternal(&tail, init, ty, &offset, &error); if (error) return; init->idata = header.next; prev = NULL; curr = init->idata; while (curr) { if (prev != NULL && prev->offset == curr->offset) { prev->expr = BORBitField(prev->expr, curr->expr); prev->next = curr->next; curr = curr->next; } else { prev = curr; curr = curr->next; } } }
static AstExpression CheckConditionalExpression(AstExpression expr) { int qual; Type ty1, ty2; expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (! IsScalarType(expr->kids[0]->ty)) { Error(&expr->coord, "The first expression shall be scalar type."); } expr->kids[1]->kids[0] = Adjust(CheckExpression(expr->kids[1]->kids[0]), 1); expr->kids[1]->kids[1] = Adjust(CheckExpression(expr->kids[1]->kids[1]), 1); ty1 = expr->kids[1]->kids[0]->ty; ty2 = expr->kids[1]->kids[1]->ty; if (BothArithType(ty1, ty2)) { expr->ty = CommonRealType(ty1, ty2); expr->kids[1]->kids[0] = Cast(expr->ty, expr->kids[1]->kids[0]); expr->kids[1]->kids[1] = Cast(expr->ty, expr->kids[1]->kids[1]); return FoldConstant(expr); } else if (IsRecordType(ty1) && ty1 == ty2) { expr->ty = ty1; } else if (ty1->categ == VOID && ty2->categ == VOID) { expr->ty = T(VOID); } else if (IsCompatiblePtr(ty1, ty2)) { qual = ty1->bty->qual | ty2->bty->qual; expr->ty = PointerTo(Qualify(qual, CompositeType(Unqual(ty1->bty), Unqual(ty2->bty)))); } else if (IsPtrType(ty1) && IsNullConstant(expr->kids[1]->kids[1])) { expr->ty = ty1; } else if (IsPtrType(ty2) && IsNullConstant(expr->kids[1]->kids[0])) { expr->ty = ty2; } else if (NotFunctionPtr(ty1) && IsVoidPtr(ty2) || NotFunctionPtr(ty2) && IsVoidPtr(ty1)) { qual = ty1->bty->qual | ty2->bty->qual; expr->ty = PointerTo(Qualify(qual, T(VOID))); } else { Error(&expr->coord, "invalid operand for ? operator."); expr->ty = T(INT); } return expr; }
/* * Unmarshal an array argument. * * @param msg The message * @param sig The array element signature * @param arg Pointer to the structure to return the array */ static AJ_Status UnmarshalArray(AJ_Message* msg, const char** sig, AJ_Arg* arg, uint8_t pad) { AJ_Status status; AJ_IOBuffer* ioBuf = &msg->bus->sock.rx; char typeId = **sig; uint32_t numBytes; /* * Get the byte count for the array */ status = LoadBytes(ioBuf, 4, pad); if (status != AJ_OK) { return status; } EndianSwap(msg, AJ_ARG_UINT32, ioBuf->readPtr, 1); numBytes = *((uint32_t*)ioBuf->readPtr); ioBuf->readPtr += 4; /* * We are already aligned on 4 byte boundary but there may be padding after the array length if * the array element types align on an 8 byte boundary. */ pad = PadForType(typeId, ioBuf); status = LoadBytes(ioBuf, numBytes, pad); if (status != AJ_OK) { return status; } arg->val.v_data = ioBuf->readPtr; arg->sigPtr = *sig; arg->len = numBytes; if (IsScalarType(typeId)) { /* * For scalar types we do an inplace endian swap (if needed) and return a pointer into the read buffer. */ EndianSwap(msg, typeId, (void*)arg->val.v_data, arg->len); ioBuf->readPtr += numBytes; arg->typeId = typeId; arg->flags = AJ_ARRAY_FLAG; } else { /* * For all other types the elements must be individually unmarshalled. */ arg->typeId = AJ_ARG_ARRAY; } /* * Consume the array element signature. */ *sig += CompleteTypeSigLen(*sig); return status; }
AJ_Status AJ_UnmarshalArgs(AJ_Message* msg, const char* sig, ...) { AJ_Status status = AJ_OK; AJ_Arg arg; va_list argp; va_start(argp, sig); while (*sig) { uint8_t typeId = (uint8_t)*sig++; void* val = va_arg(argp, void*); if (!IsBasicType(typeId)) { status = AJ_ERR_UNEXPECTED; break; } status = AJ_UnmarshalArg(msg, &arg); if (status != AJ_OK) { break; } if (arg.typeId != typeId) { status = AJ_ERR_UNMARSHAL; break; } if (IsScalarType(typeId)) { switch (SizeOfType(typeId)) { case 1: *((uint8_t*)val) = *arg.val.v_byte; break; case 2: *((uint16_t*)val) = *arg.val.v_uint16; break; case 4: *((uint32_t*)val) = *arg.val.v_uint32; break; case 8: *((uint64_t*)val) = *arg.val.v_uint64; break; } } else { *((const char**)val) = arg.val.v_string; } } va_end(argp); return status; }
CastExpression_up CastExpression::CreateBaseTypeCast( Type cast_type, Expression_up cast_expression, bool is_explicit ) { Type expression_type = cast_expression->GetType().GetType(); if( IsScalarType( expression_type ) ) return Create( cast_type, std::move(cast_expression), is_explicit ); assert( IsVectorType( expression_type ) && "Unhandled type in CreateBaseTypeCase" ); // Find the correct cast_type return Create( GetVectorType( cast_type, GetNumElementsInType( expression_type ) ), std::move(cast_expression), is_explicit ); }
AJ_Status AJ_MarshalArgs(AJ_Message* msg, const char* sig, ...) { AJ_Status status = AJ_OK; AJ_Arg arg; va_list argp; va_start(argp, sig); while (*sig) { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; uint8_t typeId = (uint8_t)*sig++; void* val; if (!IsBasicType(typeId)) { status = AJ_ERR_UNEXPECTED; break; } if (IsScalarType(typeId)) { if (SizeOfType(typeId) == 8) { u64 = va_arg(argp, uint64_t); val = &u64; } else if (SizeOfType(typeId) == 4) { u32 = va_arg(argp, uint32_t); val = &u32; } else if (SizeOfType(typeId) == 2) { u16 = (uint16_t)va_arg(argp, uint32_t); val = &u16; } else { u8 = (uint8_t)va_arg(argp, uint32_t); val = &u8; } } else { val = va_arg(argp, char*); } InitArg(&arg, typeId, val); status = AJ_MarshalArg(msg, &arg); if (status != AJ_OK) { break; } } va_end(argp); return status; }
static AstInitializer CheckInitializerInternal(InitData *tail, AstInitializer init, Type ty, int *offset, int *error) { AstInitializer p; int size = 0; InitData initd; if (IsScalarType(ty)) { p = init; if (init->lbrace) { Error(&init->coord, "Can't use brace-enclosed initializer list for scalar"); *error = 1; p = (AstInitializer)init->initials; } p->expr = Adjust(CheckExpression(p->expr), 1); if (! CanAssign(ty, p->expr)) { Error(&init->coord, "Wrong initializer"); *error = 1; } else { p->expr = Cast(ty, p->expr); } ALLOC(initd); initd->offset = *offset; initd->expr = p->expr; initd->next = NULL; (*tail)->next = initd; *tail = initd; return (AstInitializer)init->next; } else if (ty->categ == UNION) { p = init->lbrace ? (AstInitializer)init->initials : init; ty = ((RecordType)ty)->flds->ty; p = CheckInitializerInternal(tail, p, ty, offset, error); if (init->lbrace) { if (p != NULL) { Error(&init->coord, "too many initializer for union"); } return (AstInitializer)init->next; } return p; } else if (ty->categ == ARRAY) { int start = *offset; p = init->lbrace ? (AstInitializer)init->initials : init; if (((init->lbrace && ! p->lbrace && p->next == NULL) || ! init->lbrace) && p->expr->op == OP_STR && ty->categ / 2 == p->expr->ty->categ / 2) { size = p->expr->ty->size; if (ty->size == 0 || ty->size == size) { ty->size = size; } else if (ty->size == size - 1) { p->expr->ty->size = size - 1; } else if (ty->size < size) { Error(&init->coord, "string is too long"); *error = 1; } ALLOC(initd); initd->offset = *offset; initd->expr = p->expr; initd->next = NULL; (*tail)->next = initd; *tail = initd; return (AstInitializer)init->next; } while (p != NULL) { p = CheckInitializerInternal(tail, p, ty->bty, offset, error); size += ty->bty->size; *offset = start + size; if (ty->size == size) break; } if (ty->size == 0) { ty->size = size; } else if (ty->size < size) { Error(&init->coord, "too many initializer"); *error = 1; } if (init->lbrace) { return (AstInitializer)init->next; } return p; } else if (ty->categ == STRUCT) { int start = *offset; Field fld = ((RecordType)ty)->flds; p = init->lbrace ? (AstInitializer)init->initials : init; while (fld && p) { *offset = start + fld->offset; p = CheckInitializerInternal(tail, p, fld->ty, offset, error); if (fld->bits != 0) { (*tail)->expr = PlaceBitField(fld, (*tail)->expr); } fld = fld->next; } if (init->lbrace) { if (p != NULL) { Error(&init->coord, "too many initializer"); *error = 1; } *offset = ty->size; return (AstInitializer)init->next; } return (AstInitializer)p; } return init; }
GLOBAL void ConstFoldCast(Node *node) { Node *expr; Node *from_type, *to_type; BasicType from_basic, to_basic; /* this function works on both casts and implicitcasts */ switch (node->typ) { case Cast: expr = node->u.cast.expr; break; case ImplicitCast: expr = node->u.implicitcast.expr; if (expr == NULL) return; break; default: UNREACHABLE; } if (!NodeIsConstant(expr)) return; to_type = NodeDataType(node); from_type = NodeDataType(expr); /* can only constant-fold scalar expressions (integral, floating, and pointer) */ if (IsScalarType(to_type) && IsScalarType(from_type)) { from_basic = BasicTypeOfConstantValue(from_type); to_basic = BasicTypeOfConstantValue(to_type); switch (to_basic) { case Slonglong: case Ulonglong: case Longdouble: /* fix: cannot represent these types internally, so no constant-folding occurs. */ return; default: break; } switch (from_basic) { case Sint: { int eval = NodeConstantSintValue(expr); switch (to_basic) { case Sint: NodeSetSintValue(node, eval); return; case Uint: NodeSetUintValue(node, eval); return; case Slong: NodeSetSlongValue(node, eval); return; case Ulong: NodeSetUlongValue(node, eval); return; case Float: NodeSetFloatValue(node, eval); return; case Double: NodeSetDoubleValue(node, eval); return; default: UNREACHABLE; } } case Uint: { unsigned eval = NodeConstantUintValue(expr); switch (to_basic) { case Sint: NodeSetSintValue(node, eval); return; case Uint: NodeSetUintValue(node, eval); return; case Slong: NodeSetSlongValue(node, eval); return; case Ulong: NodeSetUlongValue(node, eval); return; case Float: NodeSetFloatValue(node, eval); return; case Double: NodeSetDoubleValue(node, eval); return; default: UNREACHABLE; } } case Slong: { long eval = NodeConstantSlongValue(expr); switch (to_basic) { case Sint: NodeSetSintValue(node, eval); return; case Uint: NodeSetUintValue(node, eval); return; case Slong: NodeSetSlongValue(node, eval); return; case Ulong: NodeSetUlongValue(node, eval); return; case Float: NodeSetFloatValue(node, eval); return; case Double: NodeSetDoubleValue(node, eval); return; default: UNREACHABLE; } } case Ulong: { unsigned long eval = NodeConstantUlongValue(expr); switch (to_basic) { case Sint: NodeSetSintValue(node, eval); return; case Uint: NodeSetUintValue(node, eval); return; case Slong: NodeSetSlongValue(node, eval); return; case Ulong: NodeSetUlongValue(node, eval); return; case Float: NodeSetFloatValue(node, eval); return; case Double: NodeSetDoubleValue(node, eval); return; default: UNREACHABLE; } } case Float: { float eval = NodeConstantFloatValue(expr); switch (to_basic) { case Sint: NodeSetSintValue(node, eval); return; case Uint: NodeSetUintValue(node, eval); return; case Slong: NodeSetSlongValue(node, eval); return; case Ulong: NodeSetUlongValue(node, eval); return; case Float: NodeSetFloatValue(node, eval); return; case Double: NodeSetDoubleValue(node, eval); return; default: UNREACHABLE; } } case Double: { double eval = NodeConstantDoubleValue(expr); switch (to_basic) { case Sint: NodeSetSintValue(node, eval); return; case Uint: NodeSetUintValue(node, eval); return; case Slong: NodeSetSlongValue(node, eval); return; case Ulong: NodeSetUlongValue(node, eval); return; case Float: NodeSetFloatValue(node, eval); return; case Double: NodeSetDoubleValue(node, eval); return; default: UNREACHABLE; } } default: UNREACHABLE; } } }
/* * Unmarshal a single argument */ static AJ_Status Unmarshal(AJ_Message* msg, const char** sig, AJ_Arg* arg) { AJ_Status status; AJ_IOBuffer* ioBuf = &msg->bus->sock.rx; char typeId; uint32_t pad; uint32_t sz; memset(arg, 0, sizeof(AJ_Arg)); if (!*sig || !**sig) { return AJ_ERR_END_OF_DATA; } typeId = **sig; *sig += 1; pad = PadForType(typeId, ioBuf); if (IsScalarType(typeId)) { sz = SizeOfType(typeId); status = LoadBytes(ioBuf, sz, pad); if (status != AJ_OK) { return status; } /* * For numeric types we just return a pointer into the buffer */ arg->typeId = typeId; arg->val.v_byte = ioBuf->readPtr; arg->len = 0; ioBuf->readPtr += sz; EndianSwap(msg, typeId, (void*)arg->val.v_data, 1); } else if (TYPE_FLAG(typeId) & (AJ_STRING | AJ_VARIANT)) { /* * Length field for a signature is 1 byte, for regular strings its 4 bytes */ uint32_t lenSize = ALIGNMENT(typeId); /* * Read the string length. Note the length doesn't include the terminating NUL * so an empty string in encoded as two zero bytes. */ status = LoadBytes(ioBuf, lenSize, pad); if (status != AJ_OK) { return status; } if (lenSize == 4) { EndianSwap(msg, AJ_ARG_UINT32, ioBuf->readPtr, 1); sz = *((uint32_t*)ioBuf->readPtr); } else { sz = (uint32_t)(*ioBuf->readPtr); } ioBuf->readPtr += lenSize; status = LoadBytes(ioBuf, sz + 1, 0); if (status != AJ_OK) { return status; } arg->typeId = typeId; arg->len = sz; arg->val.v_string = (char*)ioBuf->readPtr; ioBuf->readPtr += sz + 1; /* * If unmarshalling a variant store offset to start of signature */ if (typeId == AJ_ARG_VARIANT) { msg->varOffset = (uint8_t)(sz + 1); } } else if (typeId == AJ_ARG_ARRAY) { status = UnmarshalArray(msg, sig, arg, pad); } else if ((typeId == AJ_ARG_STRUCT) || (typeId == AJ_ARG_DICT_ENTRY)) { arg->typeId = typeId; status = UnmarshalStruct(msg, sig, arg, pad); } else { status = AJ_ERR_UNMARSHAL; } return status; }
static AJ_Status Marshal(AJ_Message* msg, const char** sig, AJ_Arg* arg) { AJ_Status status = AJ_OK; AJ_IOBuffer* ioBuf = &msg->bus->sock.tx; char typeId = **sig; uint32_t pad = PadForType(typeId, ioBuf); size_t sz; if (!arg) { return AJ_ERR_NULL; } *sig += 1; if (IsScalarType(arg->typeId)) { if (arg->flags & AJ_ARRAY_FLAG) { if ((typeId != AJ_ARG_ARRAY) || (**sig != arg->typeId)) { return AJ_ERR_MARSHAL; } *sig += 1; sz = arg->len; status = WriteBytes(msg, &sz, 4, pad); if (status == AJ_OK) { /* * May need to pad if the elements required 8 byte alignment */ pad = PadForType(arg->typeId, ioBuf); } } else { if (typeId != arg->typeId) { return AJ_ERR_MARSHAL; } sz = SizeOfType(typeId); } if (status == AJ_OK) { status = WriteBytes(msg, arg->val.v_data, sz, pad); } } else if (TYPE_FLAG(typeId) & (AJ_STRING | AJ_VARIANT)) { if (typeId != arg->typeId) { return AJ_ERR_MARSHAL; } sz = arg->len ? arg->len : strlen(arg->val.v_string); /* * Length field for a signature is 1 byte, for regular strings its 4 bytes */ if (ALIGNMENT(typeId) == 1) { uint8_t szu8 = (uint8_t)sz; if (sz > 255) { return AJ_ERR_MARSHAL; } status = WriteBytes(msg, &szu8, 1, pad); } else { status = WriteBytes(msg, &sz, 4, pad); } if (status == AJ_OK) { status = WriteBytes(msg, arg->val.v_string, sz, 0); /* * String must be NUL terminated on the wire */ if (status == AJ_OK) { status = WritePad(msg, 1); } /* * If marshalling a variant store offset to start of signature */ if (typeId == AJ_ARG_VARIANT) { msg->varOffset = (uint8_t)(sz + 1); } } } else if (TYPE_FLAG(typeId) & AJ_CONTAINER) { if (typeId != arg->typeId) { return AJ_ERR_MARSHAL; } status = MarshalContainer(msg, sig, arg, pad); } else { return AJ_ERR_MARSHAL; } return status; }
static AstExpression CheckUnaryExpression(AstExpression expr) { Type ty; switch (expr->op) { case OP_PREINC: case OP_PREDEC: return TransformIncrement(expr); case OP_ADDRESS: expr->kids[0] = CheckExpression(expr->kids[0]); ty = expr->kids[0]->ty; if (expr->kids[0]->op == OP_DEREF) { expr->kids[0]->kids[0]->lvalue = 0; return expr->kids[0]->kids[0]; } else if (expr->kids[0]->op == OP_INDEX) { expr->kids[0]->op = OP_ADD; expr->kids[0]->ty = PointerTo(ty); expr->kids[0]->lvalue = 0; return expr->kids[0]; } else if (IsFunctionType(ty) || (expr->kids[0]->lvalue && ! expr->kids[0]->bitfld && ! expr->kids[0]->inreg)) { expr->ty = PointerTo(ty); return expr; } break; case OP_DEREF: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); ty = expr->kids[0]->ty; if (expr->kids[0]->op == OP_ADDRESS) { expr->kids[0]->kids[0]->ty = ty->bty; return expr->kids[0]->kids[0]; } else if (expr->kids[0]->op == OP_ADD && expr->kids[0]->kids[0]->isarray) { expr->kids[0]->op = OP_INDEX; expr->kids[0]->ty = ty->bty; expr->kids[0]->lvalue = 1; return expr->kids[0]; } if (IsPtrType(ty)) { expr->ty = ty->bty; if (IsFunctionType(expr->ty)) { return expr->kids[0]; } expr->lvalue = 1; return expr; } break; case OP_POS: case OP_NEG: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (IsArithType(expr->kids[0]->ty)) { expr->kids[0] = DoIntegerPromotion(expr->kids[0]); expr->ty = expr->kids[0]->ty; return expr->op == OP_POS ? expr->kids[0] : FoldConstant(expr); } break; case OP_COMP: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (IsIntegType(expr->kids[0]->ty)) { expr->kids[0] = DoIntegerPromotion(expr->kids[0]); expr->ty = expr->kids[0]->ty; return FoldConstant(expr); } break; case OP_NOT: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (IsScalarType(expr->kids[0]->ty)) { expr->ty = T(INT); return FoldConstant(expr); } break; case OP_SIZEOF: if (expr->kids[0]->kind == NK_Expression) { expr->kids[0] = CheckExpression(expr->kids[0]); if (expr->kids[0]->bitfld) goto err; ty = expr->kids[0]->ty; } else { ty = CheckTypeName((AstTypeName)expr->kids[0]); } if (IsFunctionType(ty) || ty->size == 0) goto err; expr->ty = T(UINT); expr->op = OP_CONST; expr->val.i[0] = ty->size; return expr; case OP_CAST: return CheckTypeCast(expr); default: assert(0); } err: REPORT_OP_ERROR; }