mp_integer compute_pointer_offset( const namespacet &ns, const exprt &expr) { if(expr.id()==ID_symbol) return 0; else if(expr.id()==ID_index) { assert(expr.operands().size()==2); const typet &array_type=ns.follow(expr.op0().type()); assert(array_type.id()==ID_array); mp_integer o=compute_pointer_offset(ns, expr.op0()); if(o!=-1) { mp_integer sub_size= pointer_offset_size(ns, array_type.subtype()); mp_integer i; if(sub_size!=0 && !to_integer(expr.op1(), i)) return o+i*sub_size; } // don't know } else if(expr.id()==ID_member) { assert(expr.operands().size()==1); const typet &type=ns.follow(expr.op0().type()); assert(type.id()==ID_struct || type.id()==ID_union); mp_integer o=compute_pointer_offset(ns, expr.op0()); if(o!=-1) { if(type.id()==ID_union) return o; return o+member_offset( ns, to_struct_type(type), expr.get(ID_component_name)); } } else if(expr.id()==ID_string_constant) return 0; return -1; // don't know }
void initialize_in_object(O& object, Context* context) const override { PluralAssociationBase<O, HasMany<A>>::initialize_in_object(object, context); // This is sinful (and undefined behaviour, and probably slow: // The aim is to be able to go from pointer to HasMany<A> to pointer to O. size_t offset = member_offset(object); this->get(object)->get_id_of_owner_ = [=](const HasMany<A>& anchor) -> PrimaryKey { const O* obj = reinterpret_cast<const O*>(reinterpret_cast<const char*>(&anchor) - offset); auto t = get_type<O>()->primary_key(); auto p = dynamic_cast<const PropertyOfBase<O, PrimaryKey>*>(t); if (p == nullptr) { throw AssociationError{"Owner of HasMany association has a primary key that isn't a PrimaryKey property."}; } return p->get_known(*obj); }; }
void cvc_convt::convert_address_of_rec(const exprt &expr) { if(expr.id()==ID_symbol || expr.id()==ID_constant || expr.id()==ID_string_constant) { out << "(# object:=" << pointer_logic.add_object(expr) << ", offset:=" << bin_zero(config.ansi_c.pointer_width) << " #)"; } else if(expr.id()==ID_index) { if(expr.operands().size()!=2) throw "index takes two operands"; const exprt &array=expr.op0(); const exprt &index=expr.op1(); if(index.is_zero()) { if(array.type().id()==ID_pointer) convert_expr(array); else if(array.type().id()==ID_array) convert_address_of_rec(array); else assert(false); } else { out << "(LET P: "; out << cvc_pointer_type(); out << " = "; if(array.type().id()==ID_pointer) convert_expr(array); else if(array.type().id()==ID_array) convert_address_of_rec(array); else assert(false); out << " IN P WITH .offset:=BVPLUS(" << config.ansi_c.pointer_width << ", P.offset, "; convert_expr(index); out << "))"; } } else if(expr.id()==ID_member) { if(expr.operands().size()!=1) throw "member takes one operand"; const exprt &struct_op=expr.op0(); out << "(LET P: "; out << cvc_pointer_type(); out << " = "; convert_address_of_rec(struct_op); const irep_idt &component_name= to_member_expr(expr).get_component_name(); mp_integer offset=member_offset( to_struct_type(struct_op.type()), component_name, ns); typet index_type(ID_unsignedbv); index_type.set(ID_width, config.ansi_c.pointer_width); exprt index=from_integer(offset, index_type); out << " IN P WITH .offset:=BVPLUS(" << config.ansi_c.pointer_width << ", P.offset, "; convert_expr(index); out << "))"; } else throw "don't know how to take address of: "+expr.id_string(); }
/* * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ clude <stdio.h> #include <guk/sched.h> #include <list.h> #define member_offset(member) \ (unsigned long)(&((struct thread *)0)->member) #define listmember_offset(member) \ (unsigned long)(&((struct list_head *)0)->member) int main (int argc, char **argv) { printf("STRUCT_THREAD_SIZE %d\n", sizeof(struct thread)); printf(" PREEMPT_COUNT_OFFSET %d\n", member_offset(preempt_count)); printf(" STACK_OFFSET %d\n", member_offset(stack)); printf(" FLAGS_OFFSET %d\n", member_offset(flags)); printf(" REGS_OFFSET %d\n", member_offset(regs)); printf(" FPREGS_OFFSET %d\n", member_offset(fpregs)); printf(" ID_OFFSET %d\n", member_offset(id)); printf(" APPSCHED_ID_OFFSET %d\n", member_offset(appsched_id)); printf(" GUK_STACK_ALLOCATED_OFFSET %d\n", member_offset(guk_stack_allocated)); printf(" NAME_OFFSET %d\n", member_offset(name)); printf(" STACK_OFFSET %d\n", member_offset(stack)); printf(" STACK_SIZE_OFFSET %d\n", member_offset(stack_size)); printf(" SPECIFIC_OFFSET %d\n", member_offset(specific)); printf(" TIMESLICE_OFFSET %d\n", member_offset(timeslice)); printf(" RESCHED_RUNNING_TIME_OFFSET %d\n", member_offset(resched_running_time)); printf(" START_RUNNING_TIME_OFFSET %d\n", member_offset(start_running_time)); printf(" CUM_RUNNING_TIME_OFFSET %d\n", member_offset(cum_running_time)); printf(" CPU_OFFSET %d\n", member_offset(cpu)); printf(" LOCK_COUNT_OFFSET %d\n", member_offset(lock_count)); printf(" SP_OFFSET %d\n", member_offset(sp)); printf(" IP_OFFSET %d\n", member_offset(ip)); printf(" THREAD_LIST_OFFSET %d\n", member_offset(thread_list)); printf(" READY_LIST_OFFSET %d\n", member_offset(ready_list)); printf(" JOINERS_OFFSET %d\n", member_offset(joiners)); printf(" AUX_THREAD_LIST_OFFSET %d\n", member_offset(aux_thread_list)); printf(" DB_DATA_OFFSET %d\n", member_offset(db_data)); printf("STRUCT_LIST_HEAD_SIZE %d\n", sizeof(struct list_head)); printf(" NEXT_OFFSET %d\n", listmember_offset(next)); printf(" PREV_OFFSET %d\n", listmember_offset(prev)); }
namespace TaggedFormat { const char * BasicMeshText = "Test-mesh: mesh triangles\n" " indices: array index16\n" " 0 1 2 3 4 5 6 7 8 9 10 11" " end\n" " vertices: array vertex-p3n3m2\n" " 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0\n" " 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0\n" " 1.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0\n" " 1.0 1.0 0.0 0.0 0.0 1.0 1.0 1.0\n" " 0.0 1.0 0.0 0.0 0.0 1.0 0.0 1.0\n" " end\n" " axes: array axis\n" " Test 1.0 2.0 3.0 4.0 5.0 6.0 7.0" " end\n" "end\n" "top: $Test-mesh\n"; UnitTest::Suite MeshTestSuite { "Test Mesh", {"Check Mesh Data Structure Alignment", [](UnitTest::Examiner & examiner) { examiner.check_equal(sizeof(Index16), 2); examiner.check_equal(sizeof(Index32), 4); examiner.check_equal(member_offset(&VertexP3N3M2C4::position), 0); examiner.check_equal(member_offset(&VertexP3N3M2C4::normal), 12); examiner.check_equal(member_offset(&VertexP3N3M2C4::mapping), 24); examiner.check_equal(member_offset(&VertexP3N3M2C4::color), 32); } }, {"Test Parser", [](UnitTest::Examiner & examiner) { std::stringstream input(BasicMeshText); Buffers::DynamicBuffer buffer; Parser::serialize(input, buffer); Reader reader(buffer); auto mesh = reader.block_at_offset<Mesh>(reader.header()->top_offset); examiner.check(mesh); auto indices = reader.array_at_offset<Index16>(mesh->indices_offset); examiner.check(indices); examiner.check_equal(indices->count(), 12); for (std::size_t i = 0; i != indices->count(); i += 1) { examiner.check_equal(indices->at(i).value, i); } auto vertices = reader.array_at_offset<VertexP3N3M2>(mesh->vertices_offset); examiner.check(vertices); examiner.check_equal(vertices->count(), 5); examiner << "Check that enumeration works correctly." << std::endl; std::size_t count = 0; for (auto vertex : *vertices) { count += vertex.position[0]; } examiner.check_equal(count, 2); examiner.check_equal(vertices->at(0).position[0], 0.0); examiner.check_equal(vertices->at(0).position[1], 1.0); examiner.check_equal(vertices->at(0).position[2], 2.0); examiner.check_equal(vertices->at(0).normal[0], 3.0); examiner.check_equal(vertices->at(0).normal[1], 4.0); examiner.check_equal(vertices->at(0).normal[2], 5.0); examiner.check_equal(vertices->at(0).mapping[0], 6.0); examiner.check_equal(vertices->at(0).mapping[1], 7.0); auto axes = reader.block_at_offset<Axes>(mesh->axes_offset); examiner.check(axes); examiner.check_equal(axes->count(), 1); examiner.check_equal(axes->at(0).translation[0], 1.0); examiner.check_equal(axes->at(0).translation[1], 2.0); examiner.check_equal(axes->at(0).translation[2], 3.0); examiner.check_equal(axes->at(0).rotation[0], 4.0); examiner.check_equal(axes->at(0).rotation[1], 5.0); examiner.check_equal(axes->at(0).rotation[2], 6.0); examiner.check_equal(axes->at(0).rotation[3], 7.0); } }, }; }
namespace TaggedFormat { const char * BasicSkeletonText = "Model-animation: array skeleton-animation-key-frame\n" " 1 linear 0.0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1\n" " 1 linear 30.0 1 0 0 0 0 1 0 0 0 0 1 0 0 10 0 1\n" "end\n" "Model-skeleton: skeleton\n" " bones: array skeleton-bone\n" " BoneA 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1\n" " BoneB 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 10 1\n" " end\n" " sequences: offset-table\n" " default: skeleton-animation 15.0 30.0\n" " key-frames: $Model-animation\n" " end\n" " end\n" "end\n" "top: $Model-skeleton\n"; std::array<float32, 16> IdentityMatrix = { {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1} }; UnitTest::Suite SkeletonTestSuite { "Test Skeleton Data Structures", {"Check Alignment", [](UnitTest::Examiner & examiner) { examiner.check_equal(member_offset(&SkeletonBone::name), 0); examiner.check_equal(member_offset(&SkeletonBone::parent), 32); examiner.check_equal(member_offset(&SkeletonBone::transform), 36); } }, {"Test Parser", [](UnitTest::Examiner & examiner) { std::stringstream input(BasicSkeletonText); Buffers::DynamicBuffer buffer; Parser::serialize(input, buffer); Reader reader(buffer); auto skeleton = reader.block_at_offset<Skeleton>(reader.header()->top_offset); examiner.check(skeleton); auto bones = reader.array_at_offset<SkeletonBone>(skeleton->bones_offset); examiner.check(bones); examiner.check_equal(bones->count(), 2); examiner.check_equal(bones->at(0).parent, 0); examiner.check_equal(bones->at(1).parent, 0); examiner.check_equal(bones->at(0).name, "BoneA"); examiner.check_equal(bones->at(1).name, "BoneB"); for (std::size_t i = 0; i < 16; i += 1) examiner.check_equal(IdentityMatrix[i], bones->at(0).transform[i]); auto sequences = reader.block_at_offset<OffsetTable>(skeleton->sequences_offset); examiner.check(sequences); OffsetT default_sequence = sequences->offset_named("default"); auto animation = reader.block_at_offset<SkeletonAnimation>(default_sequence); examiner.check(animation); examiner.check_equal(animation->start_time, 15.0); examiner.check_equal(animation->end_time, 30.0); OffsetT bone_key_frames_offset = animation->key_frames_offset; auto bone_key_frames = reader.array_at_offset<SkeletonAnimationKeyFrame>(bone_key_frames_offset); examiner.check(bone_key_frames); examiner.check_equal(bone_key_frames->count(), 2); } }, {"Test Vertex Formats", [](UnitTest::Examiner & examiner) { const char * BasicSkeletonMeshText = "top: mesh triangles\n" " vertices: array vertex-p3n3m2b4\n" " 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 1 2 3 4 0.60 0.20 0.15 0.05\n" " end\n" "end\n"; std::stringstream input(BasicSkeletonMeshText); Buffers::DynamicBuffer buffer; Parser::serialize(input, buffer); Reader reader(buffer); examiner << "Load the mesh block." << std::endl; auto mesh = reader.block_at_offset<Mesh>(reader.header()->top_offset); examiner.check(mesh); examiner << "Load the vertices block." << std::endl; auto vertices = reader.array_at_offset<VertexP3N3M2B4>(mesh->vertices_offset); examiner.check(vertices); examiner << "Check the number of vertices." << std::endl; examiner.check_equal(vertices->count(), 1); examiner.check_equal(vertices->at(0).bones[0], 1); examiner.check_equal(vertices->at(0).bones[1], 2); examiner.check_equal(vertices->at(0).bones[2], 3); examiner.check_equal(vertices->at(0).bones[3], 4); } }, }; }
bool simplify_exprt::simplify_address_of_arg(exprt &expr) { if(expr.id()==ID_index) { if(expr.operands().size()==2) { bool result=true; if(!simplify_address_of_arg(expr.op0())) result=false; if(!simplify_rec(expr.op1())) result=false; // rewrite (*(type *)int) [index] by // pushing the index inside mp_integer address; if(is_dereference_integer_object(expr.op0(), address)) { // push index into address mp_integer step_size, index; step_size=pointer_offset_size(expr.type(), ns); if(!to_integer(expr.op1(), index) && step_size!=-1) { unsignedbv_typet int_type(config.ansi_c.pointer_width); pointer_typet pointer_type; pointer_type.subtype()=expr.type(); typecast_exprt typecast_expr( from_integer(step_size*index+address, int_type), pointer_type); exprt new_expr=dereference_exprt(typecast_expr, expr.type()); expr=new_expr; result=true; } } return result; } } else if(expr.id()==ID_member) { if(expr.operands().size()==1) { bool result=true; if(!simplify_address_of_arg(expr.op0())) result=false; const typet &op_type=ns.follow(expr.op0().type()); if(op_type.id()==ID_struct) { // rewrite NULL -> member by // pushing the member inside mp_integer address; if(is_dereference_integer_object(expr.op0(), address)) { const struct_typet &struct_type=to_struct_type(op_type); const irep_idt &member=to_member_expr(expr).get_component_name(); mp_integer offset=member_offset(struct_type, member, ns); if(offset!=-1) { unsignedbv_typet int_type(config.ansi_c.pointer_width); pointer_typet pointer_type; pointer_type.subtype()=expr.type(); typecast_exprt typecast_expr( from_integer(address+offset, int_type), pointer_type); exprt new_expr=dereference_exprt(typecast_expr, expr.type()); expr=new_expr; result=true; } } } return result; } } else if(expr.id()==ID_dereference) { if(expr.operands().size()==1) return simplify_rec(expr.op0()); } else if(expr.id()==ID_if) { if(expr.operands().size()==3) { bool result=true; if(!simplify_rec(expr.op0())) result=false; if(!simplify_address_of_arg(expr.op1())) result=false; if(!simplify_address_of_arg(expr.op2())) result=false; // op0 is a constant? if(expr.op0().is_true()) { result=false; exprt tmp; tmp.swap(expr.op1()); expr.swap(tmp); } else if(expr.op0().is_false()) { result=false; exprt tmp; tmp.swap(expr.op2()); expr.swap(tmp); } return result; } } return true; }