//: Labels are defined by ending names with a ':'. This layer will compute //: displacements for labels, and compute the offset for instructions using them. //: //: We won't check this, but our convention will be that jump targets will //: start with a '$', while functions will not. Function names will never be //: jumped to, and jump targets will never be called. //: We're introducing non-number names for the first time, so it's worth //: laying down some ground rules all transforms will follow, so things don't //: get too confusing: //: - if it starts with a digit, it's treated as a number. If it can't be //: parsed as hex it will raise an error. //: - if it starts with '-' it's treated as a number. //: - if it starts with '0x' it's treated as a number. //: - if it's two characters long, it can't be a name. Either it's a hex //: byte, or it raises an error. //: That's it. Names can start with any non-digit that isn't a dash. They can //: be a single character long. 'a' is not a hex number, it's a variable. //: Later layers may add more conventions partitioning the space of names. But //: the above rules will remain inviolate. //: One special label is 'Entry', the address to start running the program at. //: It can be non-unique; the last declaration overrides earlier ones. //: It must exist in a program. Otherwise we don't know where to start running //: programs. void test_Entry_label() { run( "== code 0x1\n" "05 0x0d0c0b0a/imm32\n" "Entry:\n" "05 0x0d0c0b0a/imm32\n" ); CHECK_TRACE_CONTENTS( "run: 0x00000006 opcode: 05\n" ); CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000001 opcode: 05"); } :(before "End looks_like_hex_int(s) Detectors") if (SIZE(s) == 2) return true; :(code) void test_pack_immediate_ignores_single_byte_nondigit_operand() { Hide_errors = true; transform( "== code 0x1\n" "b9/copy a/imm32\n" ); CHECK_TRACE_CONTENTS( "transform: packing instruction 'b9/copy a/imm32'\n" // no change (we're just not printing metadata to the trace) "transform: instruction after packing: 'b9 a'\n" ); } void test_pack_immediate_ignores_3_hex_digit_operand() { Hide_errors = true; transform( "== code 0x1\n" "b9/copy aaa/imm32\n" ); CHECK_TRACE_CONTENTS( "transform: packing instruction 'b9/copy aaa/imm32'\n" // no change (we're just not printing metadata to the trace) "transform: instruction after packing: 'b9 aaa'\n" ); } void test_pack_immediate_ignores_non_hex_operand() { Hide_errors = true; transform( "== code 0x1\n" "b9/copy xxx/imm32\n" ); CHECK_TRACE_CONTENTS( "transform: packing instruction 'b9/copy xxx/imm32'\n" // no change (we're just not printing metadata to the trace) "transform: instruction after packing: 'b9 xxx'\n" ); } //: a helper we'll find handy later void check_valid_name(const string& s) { if (s.empty()) { raise << "empty name!\n" << end(); return; } if (s.at(0) == '-') raise << "'" << s << "' starts with '-', which can be confused with a negative number; use a different name\n" << end(); if (s.substr(0, 2) == "0x") { raise << "'" << s << "' looks like a hex number; use a different name\n" << end(); return; } if (isdigit(s.at(0))) raise << "'" << s << "' starts with a digit, and so can be confused with a number; use a different name.\n" << end(); if (SIZE(s) == 2) raise << "'" << s << "' is two characters long, which can look lik
*~
*.pyc
*.pyo
stuff/*