2 * Copyright (c) 1996 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
42 // $Id: BPatch_snippet.C,v 1.31 2001/08/29 23:25:27 hollings Exp $
50 #include "instPoint.h"
53 #include "BPatch_snippet.h"
54 #include "BPatch_type.h"
55 #include "BPatch_collections.h"
56 #include "BPatch_Vector.h"
57 #include "common/h/Time.h"
58 #include "common/h/timing.h"
61 * BPatch_snippet::BPatch_snippet
63 * Copy constructor for BPatch_snippet.
65 BPatch_snippet::BPatch_snippet(const BPatch_snippet &src)
67 ast = assignAst(src.ast);
72 * BPatch_snippet::operator=
74 * Assignment operator for BPatch_snippet. Needed to ensure that the
75 * reference counts for the asts contained in the snippets is correct.
77 BPatch_snippet &BPatch_snippet::operator=(const BPatch_snippet &src)
83 // Since we're copying over this snippet, release the old AST
87 // We'll now contain another reference to the ast in the other snippet
88 ast = assignAst(src.ast);
95 * BPatch_snippet:getCost
97 * Returns the estimated cost of executing the snippet, in seconds.
99 float BPatch_snippet::getCost()
101 timeLength costv = timeLength(ast->cost(), getCyclesPerSecond());
102 float retCost = static_cast<float>(costv.getD(timeUnit::sec()));
108 * BPatch_snippet::~BPatch_snippet
110 * Destructor for BPatch_snippet. Deallocates memory allocated by the
113 BPatch_snippet::~BPatch_snippet()
121 // generateArrayRef - Construct an Ast expression for an array.
123 AstNode *generateArrayRef(const BPatch_snippet &lOperand,
124 const BPatch_snippet &rOperand)
128 if (!lOperand.ast || !rOperand.ast) {
131 BPatch_type *arrayType = const_cast<BPatch_type *>(lOperand.ast->getType());
133 BPatch_reportError(BPatchSerious, 109,
134 "array reference has not type information");
137 if (arrayType->getDataClass() != BPatch_dataArray) {
138 BPatch_reportError(BPatchSerious, 109,
139 "array reference to non-array type");
142 BPatch_type *elementType = arrayType->getConstituentType();
145 int elementSize = elementType->getSize();
147 // check that the type of the right operand is an integer.
148 BPatch_type *indexType = const_cast<BPatch_type *>(rOperand.ast->getType());
149 if (!indexType || strcmp(indexType->getName(), "int")) {
150 // XXX - Should really check if this is a short/long too
151 BPatch_reportError(BPatchSerious, 109,
152 "array index is not of type int");
157 // Convert a[i] into *(&a + (* i sizeof(element)))
159 AstNode *elementExpr = new AstNode(AstNode::Constant, (void *) elementSize);
160 AstNode *offsetExpr = new AstNode(timesOp, elementExpr, rOperand.ast);
161 AstNode *addrExpr = new AstNode(plusOp,
162 new AstNode(getAddrOp, lOperand.ast), offsetExpr);
163 ast = new AstNode(AstNode::DataIndir, addrExpr);
164 ast->setType(elementType);
170 * BPatch_arithExpr::BPatch_arithExpr
172 * Construct a snippet representing a binary arithmetic operation.
174 * op The desired operation.
175 * lOperand The left operand for the operation.
176 * rOperand The right operand.
178 BPatch_arithExpr::BPatch_arithExpr(BPatch_binOp op,
179 const BPatch_snippet &lOperand, const BPatch_snippet &rOperand)
181 assert(BPatch::bpatch != NULL);
201 /* XXX Not yet implemented. */
205 ast = generateArrayRef(lOperand, rOperand);
211 ast = new AstNode(lOperand.ast, rOperand.ast);
212 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
215 /* XXX handle error */
219 #ifdef alpha_dec_osf4_0
221 * A special kludge for the Alpha: there's no hardware divide on the
222 * Alpha, and our code in inst-alpha.C to call a software divide doesn't
223 * work right (yet?). So, we never generate a divOp AstNode; instead we
224 * generate a callNode AST that calls a divide function.
226 if (astOp == divOp) {
227 vector<AstNode *> args;
229 args.push_back(assignAst(lOperand.ast));
230 args.push_back(assignAst(rOperand.ast));
232 ast = new AstNode("divide", args);
237 ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
240 ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
243 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
248 * BPatch_arithExpr::BPatch_arithExpr
250 * Construct a snippet representing a unary arithmetic operation.
252 * op The desired operation.
253 * lOperand The left operand for the operation.
255 BPatch_arithExpr::BPatch_arithExpr(BPatch_unOp op,
256 const BPatch_snippet &lOperand)
258 assert(BPatch::bpatch != NULL);
261 case BPatch_negate: {
262 AstNode *negOne = new AstNode(AstNode::Constant, (void *) -1);
263 BPatch_type *type = BPatch::bpatch->stdTypes->findType("int");
264 assert(type != NULL);
266 negOne->setType(type);
267 ast = new AstNode(timesOp, negOne, lOperand.ast);
272 ast = new AstNode(getAddrOp, lOperand.ast);
273 // create a new type which is a pointer to type
274 BPatch_type *baseType = const_cast<BPatch_type *>
275 (lOperand.ast->getType());
276 BPatch_type *type = BPatch::bpatch->createPointer("<PTR>",
277 baseType, sizeof(void *));
284 ast = new AstNode(AstNode::DataIndir, lOperand.ast);
285 BPatch_type *type = const_cast<BPatch_type *> ((lOperand.ast)->getType());
286 if (!type || (type->getDataClass() != BPatch_dataPointer)) {
287 ast->setType(BPatch::bpatch->stdTypes->findType("int"));
289 ast->setType(type->getConstituentType());
295 /* XXX handle error */
299 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
303 * BPatch_boolExpr::BPatch_boolExpr
305 * Constructs a snippet representing a boolean expression.
307 * op The operator for the boolean expression.
308 * lOperand The left operand.
309 * rOperand The right operand.
311 BPatch_boolExpr::BPatch_boolExpr(BPatch_relOp op,
312 const BPatch_snippet &lOperand,
313 const BPatch_snippet &rOperand)
342 /* XXX Handle the error case here */
346 ast = new AstNode(astOp, lOperand.ast, rOperand.ast);
347 assert(BPatch::bpatch != NULL);
348 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
353 * BPatch_constExpr::BPatch_constExpr
355 * Constructs a snippet representing a constant integer value.
357 * value The desired value.
359 BPatch_constExpr::BPatch_constExpr(int value)
361 ast = new AstNode(AstNode::Constant, (void *)value);
363 assert(BPatch::bpatch != NULL);
364 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
366 BPatch_type *type = BPatch::bpatch->stdTypes->findType("int");
368 assert(type != NULL);
375 * BPatch_constExpr::BPatch_constExpr
377 * Constructs a snippet representing a constant string value.
379 * value The desired constant string.
381 BPatch_constExpr::BPatch_constExpr(const char *value)
383 ast = new AstNode(AstNode::ConstantString, (void*)const_cast<char*>(value));
385 assert(BPatch::bpatch != NULL);
386 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
388 BPatch_type *type = BPatch::bpatch->stdTypes->findType("char *");
389 assert(type != NULL);
396 * BPatch_constExpr::BPatch_constExpr
398 * Constructs a snippet representing a constant pointer.
400 * value The desired constant pointer.
402 BPatch_constExpr::BPatch_constExpr(const void *value)
404 ast = new AstNode(AstNode::Constant, (void*)const_cast<void*>(value));
406 assert(BPatch::bpatch != NULL);
407 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
409 BPatch_type *type = BPatch::bpatch->stdTypes->findType("void *");
410 assert(type != NULL);
416 #ifdef IBM_BPATCH_COMPAT
418 // this is long long only in size, it will fail if a true long long
419 // with high bits is passed.
421 BPatch_constExpr::BPatch_constExpr(long long value)
423 assert(value < 0x00000000ffffffff);
425 ast = new AstNode(AstNode::Constant, (void *)(value & 0x00000000ffffffff));
427 assert(BPatch::bpatch != NULL);
428 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
430 BPatch_type *type = BPatch::bpatch->stdTypes->findType("long long");
431 printf("size of const expr type long long is %d\n", type->getSize());
433 assert(type != NULL);
436 printf("generating long long constant\n");
441 BPatch_constExpr::BPatch_constExpr(float value)
443 // XXX fix me, puting value into int register.
444 int ivalue = (int) value;
445 BPatch_constExpr((int) ivalue);
450 * BPatch_funcCallExpr::BPatch_funcCallExpr
452 * Constructs a snippet representing a function call.
454 * func Identifies the function to call.
455 * args A vector of the arguments to be passed to the function.
457 BPatch_funcCallExpr::BPatch_funcCallExpr(
458 const BPatch_function &func,
459 const BPatch_Vector<BPatch_snippet *> &args)
461 vector<AstNode *> ast_args;
464 for (i = 0; i < args.size(); i++)
465 ast_args.push_back(assignAst(args[i]->ast));
467 ast = new AstNode(func.func->prettyName(), ast_args);
469 for (i = 0; i < args.size(); i++)
470 removeAst(ast_args[i]);
472 assert(BPatch::bpatch != NULL);
473 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
477 * BPatch_funcJumpExpr::BPatch_funcJumpExpr
479 * Constructs a snippet representing a jump to a function without
482 * func Identifies the function to jump to. */
483 BPatch_funcJumpExpr::BPatch_funcJumpExpr(
484 const BPatch_function &func)
486 #if defined(sparc_sun_solaris2_4) || defined(alpha_dec_osf4_0)
487 ast = new AstNode(func.func);
488 assert(BPatch::bpatch != NULL);
489 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
491 BPatch_reportError(BPatchSerious, 109,
492 "BPatch_funcJumpExpr is not implemented on this platform");
498 * BPatch_ifExpr::BPatch_ifExpr
500 * Constructs a snippet representing a conditional expression.
502 * conditional The conditional.
503 * tClause A snippet to execute if the conditional is true.
505 BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
506 const BPatch_snippet &tClause)
508 ast = new AstNode(ifOp, conditional.ast, tClause.ast);
510 assert(BPatch::bpatch != NULL);
511 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
516 * BPatch_ifExpr::BPatch_ifExpr
518 * Constructs a snippet representing a conditional expression with an else
521 * conditional The conditional.
522 * tClause A snippet to execute if the conditional is true.
524 BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional,
525 const BPatch_snippet &tClause,
526 const BPatch_snippet &fClause)
528 ast = new AstNode(ifOp, conditional.ast, tClause.ast, fClause.ast);
530 assert(BPatch::bpatch != NULL);
531 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
536 * BPatch_nullExpr::BPatch_nullExpr
538 * Construct a null snippet that can be used as a placeholder.
540 BPatch_nullExpr::BPatch_nullExpr()
544 assert(BPatch::bpatch != NULL);
545 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
550 * BPatch_paramExpr::BPatch_paramExpr
552 * Construct a snippet representing a parameter of the function in which
553 * the snippet is inserted.
555 * n The position of the parameter (0 is the first parameter, 1 the second,
558 BPatch_paramExpr::BPatch_paramExpr(int n)
560 ast = new AstNode(AstNode::Param, (void *)n);
562 assert(BPatch::bpatch != NULL);
563 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
568 * BPatch_retExpr::BPatch_retExpr
570 * Construct a snippet representing a return value from the function in which
571 * the snippet is inserted.
574 BPatch_retExpr::BPatch_retExpr()
576 ast = new AstNode(AstNode::ReturnVal, (void *)0);
578 assert(BPatch::bpatch != NULL);
579 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
583 * BPatch_sequence::BPatch_sequence
585 * Construct a snippet representing a sequence of snippets.
587 * items The snippets that are to make up the sequence.
589 BPatch_sequence::BPatch_sequence(const BPatch_Vector<BPatch_snippet *> &items)
591 if (items.size() == 0) {
592 // XXX do something to indicate an error
596 assert(BPatch::bpatch != NULL);
598 ast = new AstNode(items[0]->ast);
599 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
601 for (int i = 1; i < items.size(); i++) {
602 AstNode *tempAst = new AstNode(ast, items[i]->ast);
603 tempAst->setTypeChecking(BPatch::bpatch->isTypeChecked());
611 * BPatch_variableExpr::BPatch_variableExpr
613 * Construct a snippet representing a variable of the given type at the given
616 * in_process The process that the variable resides in.
617 * in_address The address of the variable in the inferior's address space.
618 * type The type of the variable.
620 BPatch_variableExpr::BPatch_variableExpr(char *in_name,
623 const BPatch_type *type) :
624 name(in_name), proc(in_process), address(in_address), scope(NULL)
626 ast = new AstNode(AstNode::DataAddr, address);
628 assert(BPatch::bpatch != NULL);
629 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
633 size = type->getSize();
637 * BPatch_variableExpr::BPatch_variableExpr
639 * Construct a snippet representing a variable of the given type and the passed
642 * in_process The process that the variable resides in.
643 * in_address The address of the variable in the inferior's address space.
644 * type The type of the variable.
645 * ast The ast expression for the variable
647 BPatch_variableExpr::BPatch_variableExpr(char *in_name,
650 const BPatch_type *type) :
651 name(in_name), proc(in_process), address(NULL), scope(NULL)
655 assert(BPatch::bpatch != NULL);
656 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
660 size = type->getSize();
665 * BPatch_variableExpr::getType
667 * Return the variable's type
670 BPatch_type *BPatch_variableExpr::getType()
672 return (const_cast<BPatch_type *>(ast->getType()));
676 * BPatch_variableExpr::setType
678 * Return the variable's type
681 void BPatch_variableExpr::setType(BPatch_type *newType)
683 size = newType->getSize();
684 ast->setType(newType);
688 * BPatch_variableExpr::BPatch_variableExpr
690 * Construct a snippet representing a variable of the given type at the given
693 * in_process The process that the variable resides in.
694 * in_address The address of the variable in the inferior's address space.
695 * type The type of the variable.
696 * frameRelative Is the address a frame offset, not absolute address
699 BPatch_variableExpr::BPatch_variableExpr(process *in_process,
701 const BPatch_type *type,
704 proc(in_process), address(in_address)
707 ast = new AstNode(AstNode::FrameAddr, address);
709 ast = new AstNode(AstNode::DataAddr, address);
712 assert(BPatch::bpatch != NULL);
713 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
715 size = type->getSize();
722 * BPatch_variableExpr::BPatch_variableExpr
724 * Construct a snippet representing an untyped variable of a given size at the
727 * in_address The address of the variable in the inferior's address space.
729 BPatch_variableExpr::BPatch_variableExpr(process *in_process,
732 proc(in_process), address(in_address), scope(NULL)
734 ast = new AstNode(AstNode::DataAddr, address);
736 assert(BPatch::bpatch != NULL);
737 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());
739 ast->setType(BPatch::bpatch->type_Untyped);
746 * BPatch_variableExpr::readValue
748 * Read the value of a variable in a thread's address space.
750 * dst A pointer to a buffer in which to place the value of the
751 * variable. It is assumed to be the same size as the variable.
753 bool BPatch_variableExpr::readValue(void *dst)
756 proc->readDataSpace(address, size, dst, true);
765 * BPatch_variableExpr::readValue
767 * Read the a given number of bytes starting at the base address of a variable
768 * in the a thread's address space.
770 * dst A pointer to a buffer in which to place the value of the
771 * variable. It is assumed to be the same size as the variable.
772 * len Number of bytes to read.
774 void BPatch_variableExpr::readValue(void *dst, int len)
776 proc->readDataSpace(address, len, dst, true);
781 * BPatch_variableExpr::writeValue
783 * Write a value into a variable in a thread's address space.
785 * dst A pointer to a buffer in which to place the value of the
786 * variable. It is assumed to be the same size as the variable.
788 * returns false if the type info isn't available (i.e. we don't know the size)
790 bool BPatch_variableExpr::writeValue(const void *src)
793 proc->writeDataSpace(address, size, src);
802 * BPatch_variableExpr::writeValue
804 * Write the a given number of bytes starting at the base address of a
805 * variable in the a thread's address space.
807 * dst A pointer to a buffer in which to place the value of the
808 * variable. It is assumed to be the same size as the variable.
810 void BPatch_variableExpr::writeValue(const void *src, int len)
812 proc->writeDataSpace(address, len, src);
816 * getComponents() - return variable expressions for all of the fields
817 * in the passed structure/union.
819 BPatch_Vector<BPatch_variableExpr *> *BPatch_variableExpr::getComponents()
822 BPatch_Vector<BPatch_field *> *fields;
823 BPatch_Vector<BPatch_variableExpr *> *retList;
825 type = const_cast<BPatch_type *>(getType());
826 if ((type->getDataClass() != BPatch_dataStructure) && (type->getDataClass() != BPatch_dataUnion)) {
830 retList = new BPatch_Vector<BPatch_variableExpr *>;
833 fields = type->getComponents();
834 for (int i=0; i < fields->size(); i++) {
836 BPatch_field *field = (*fields)[i];
837 int offset = (field->offset / 8);
839 BPatch_variableExpr *newVar;
841 // convert to *(&basrVar + offset)
842 AstNode *offsetExpr = new AstNode(AstNode::Constant, (void *) offset);
843 AstNode *addrExpr = new AstNode(plusOp,
844 new AstNode(getAddrOp, ast), offsetExpr);
845 AstNode *fieldExpr = new AstNode(AstNode::DataIndir, addrExpr);
847 newVar = new BPatch_variableExpr(const_cast<char *> (field->getName()),
848 proc, fieldExpr, const_cast<BPatch_type *>(field->_type));
849 retList->push_back(newVar);
856 * BPatch_breakPointExpr::BPatch_breakPointExpr
858 * Construct a snippet representing a breakpoint.
861 BPatch_breakPointExpr::BPatch_breakPointExpr()
863 vector<AstNode *> null_args;
865 ast = new AstNode("DYNINSTbreakPoint", null_args);
867 assert(BPatch::bpatch != NULL);
869 ast->setType(BPatch::bpatch->type_Untyped);
870 ast->setTypeChecking(BPatch::bpatch->isTypeChecked());