about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--subx/035labels.cc19
-rw-r--r--subx/037label_types.cc45
-rw-r--r--subx/ex3.subx8
-rw-r--r--subx/ex7.subx4
-rw-r--r--subx/subx.vim7
-rw-r--r--subx/vim_errors.subx34
6 files changed, 101 insertions, 16 deletions
diff --git a/subx/035labels.cc b/subx/035labels.cc
index db54d329..c7274613 100644
--- a/subx/035labels.cc
+++ b/subx/035labels.cc
@@ -53,7 +53,6 @@ loop:
 
 :(before "End Level-2 Transforms")
 Transform.push_back(rewrite_labels);
-
 :(code)
 void rewrite_labels(program& p) {
   trace(99, "transform") << "-- rewrite labels" << end();
@@ -190,19 +189,19 @@ string drop_last(const string& s) {
           # op          subop               mod             rm32          base        index         scale       r32
           # 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
 # address 1
-loop:
-loop2:
+ $loop:
+ $loop2:
 # address 1 (labels take up no space)
             05                                                                                                                              0x0d0c0b0a/imm32  # add to EAX
 # address 6
-            eb                                                                                                              loop2/disp8
+            eb                                                                                                              $loop2/disp8
 # address 8
-            eb                                                                                                              loop3/disp8
+            eb                                                                                                              $loop3/disp8
 # address 10
-loop3:
-+transform: label 'loop' is at address 1
-+transform: label 'loop2' is at address 1
-+transform: label 'loop3' is at address 10
+ $loop3:
++transform: label '$loop' is at address 1
++transform: label '$loop2' is at address 1
++transform: label '$loop3' is at address 10
 # first jump is to -7
 +transform: instruction after transform: 'eb f9'
 # second jump is to 0 (fall through)
@@ -234,6 +233,6 @@ xz:
           # instruction                     effective address                                                   operand     displacement    immediate
           # op          subop               mod             rm32          base        index         scale       r32
           # 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
- -a:  # indent to avoid looking like a trace_should_not_contain command
+ -a:  # indent to avoid looking like a trace_should_not_contain command for this scenario
             05                                                                                                                              0x0d0c0b0a/imm32  # add to EAX
 +error: '-a' starts with '-', which can be confused with a negative number; use a different name
diff --git a/subx/037label_types.cc b/subx/037label_types.cc
new file mode 100644
index 00000000..b80db732
--- /dev/null
+++ b/subx/037label_types.cc
@@ -0,0 +1,45 @@
+//: Distinguish between labels marking the start of a function, and labels
+//: inside functions.
+//:
+//: - Labels within functions start with a '$', and are only permitted in
+//:   'jump' instructions.
+//:
+//: - Labels marking the start of functions lack the '$' sigil, and are only
+//:   permitted in 'call' instructions.
+
+:(before "Rewrite Labels(segment code)")
+check_label_types(code);
+if (trace_contains_errors()) return;
+:(code)
+void check_label_types(const segment& code) {
+  trace(99, "transform") << "-- check label types" << end();
+  for (int i = 0;  i < SIZE(code.lines);  ++i)
+    check_label_types(code.lines.at(i));
+}
+
+void check_label_types(const line& inst) {
+  int idx = first_operand(inst);
+  if (idx >= SIZE(inst.words)) return;
+  const word& target = inst.words.at(idx);
+  if (is_number(target.data)) return;  // handled elsewhere
+  if (is_jump(inst) && target.data.at(0) != '$')
+    raise << "'" << inst.original << "': jumps should always be to internal labels starting with '$'\n" << end();
+  if (is_call(inst) && target.data.at(0) == '$')
+    raise << "'" << inst.original << "': calls should always be to function labels (not starting with '$')\n" << end();
+}
+
+:(scenario catch_jump_to_function)
+% Hide_errors = true;
+== 0x1
+main:
+7e/jump-if foo/disp8
+foo:
++error: '7e/jump-if foo/disp8': jumps should always be to internal labels starting with '$'
+
+:(scenario catch_call_to_internal_label)
+% Hide_errors = true;
+== 0x1
+main:
+e8/call $foo/disp32
+ $foo:  # indent to avoid looking like a trace_count command for this scenario
++error: 'e8/call $foo/disp32': calls should always be to function labels (not starting with '$')
diff --git a/subx/ex3.subx b/subx/ex3.subx
index eb66f1bf..41d2b94e 100644
--- a/subx/ex3.subx
+++ b/subx/ex3.subx
@@ -16,18 +16,18 @@
   # counter: ECX = 1
   b9/copy                                                                                                                         1/imm32           # copy 1 to ECX
 
-loop:
+$loop:
   # while (counter <= 10)
   81          7/subop/compare     3/mod/direct    1/rm32/ecx                                                                      0xa/imm32         # compare ECX, 10/imm
-  7f/jump-if                                                                                                      exit/disp8                        # jump-if-greater exit
+  7f/jump-if                                                                                                      $exit/disp8                       # jump-if-greater $exit
   # result += counter
   01/add                          3/mod/direct    3/rm32/ebx                                          1/r32/ecx                                     # add ECX to EBX
   # ++counter
   81          0/subop/add         3/mod/direct    1/rm32/ecx                                                                      1/imm32           # add 1 to ECX
   # loop
-  eb/jump                                                                                                         loop/disp8                        # jump loop
+  eb/jump                                                                                                         $loop/disp8                       # jump $loop
 
-exit:
+$exit:
   # exit(EBX)
   b8/copy                                                                                                                         1/imm32           # copy 1 to EAX
   cd/syscall                                                                                                                      0x80/imm8         # int 80h
diff --git a/subx/ex7.subx b/subx/ex7.subx
index 07b2e016..b386df82 100644
--- a/subx/ex7.subx
+++ b/subx/ex7.subx
@@ -38,7 +38,7 @@ factorial:
   b8/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EAX
   # if (n <= 1) jump exit
   81          7/subop/compare     3/mod/direct    2/rm32/EDX    .           .             .           .           .               1/imm32           # compare EDX with 1
-  7e/jump-if-<=                   .               .             .           .             .           .           factorial:exit/disp8              # jump if <= to exit
+  7e/jump-if-<=                   .               .             .           .             .           .           $exit/disp8                       # jump if <= to $exit
   # EBX: n-1
   89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           2/r32/EDX   .               .                 # copy EDX to EBX
   81          5/subop/subtract    3/mod/direct    3/rm32/EBX    .           .             .           .           .               1/imm32           # subtract 1 from EBX
@@ -58,7 +58,7 @@ factorial:
   # return n * factorial(n-1)
   0f af/multiply                  3/mod/direct    2/rm32/EDX    .           .             .           0/r32/EAX   .               .                 # multiply EDX (n) into EAX (factorial(n-1))
   # TODO: check for overflow
-factorial:exit:
+$exit:
   c3/return
 
 # vim:ft=subx:nowrap:so=0
diff --git a/subx/subx.vim b/subx/subx.vim
index 17d63932..e6825c72 100644
--- a/subx/subx.vim
+++ b/subx/subx.vim
@@ -35,4 +35,11 @@ call matchadd("Warn", '\c^\s*7[45cdef].*\<\(0x\)\?[0-9a-f]\+/disp8')  " conditio
 call matchadd("Warn", '\c^\s*eb.*\<\(0x\)\?[0-9a-f]\+/disp16')  " unconditional jump disp16
 call matchadd("Warn", '\c^\s*0f[^\s]*\s*8[45cdef].*\<\(0x\)\?[0-9a-f]\+/disp16')  " conditional jump disp16
 
+" Mismatch in label type
+call matchadd("Error", '\c^\s*e8.*\$')  " call
+call matchadd("Error", '\c^\s*e9\(/[^ ]*\)\?\s*\(\.\s*\)\+[^\$\. ]\([ \$0-9a-fA-F-]\+\>\)\@!')  " unconditional jump disp8
+call matchadd("Error", '\c^\s*7[45cdef]\(/[^ ]*\)\?\s*\(\.\s*\)\+[^\$\. ]\([ \$0-9a-fA-F-]\+\>\)\@!')  " conditional jump disp8
+call matchadd("Error", '\c^\s*eb\(/[^ ]*\)\?\s*\(\.\s*\)\+[^\$\. ]\([ \$0-9a-fA-F-]\+\>\)\@!')  " unconditional jump disp16
+call matchadd("Error", '\c^\s*0f[^\s]*\s*8[45cdef]\(/[^ ]*\)\?\s*\(\.\s*\)\+[^\$\. ]\([ \$0-9a-fA-F-]\+\>\)\@!')  " conditional jump disp16
+
 let &cpo = s:save_cpo
diff --git a/subx/vim_errors.subx b/subx/vim_errors.subx
new file mode 100644
index 00000000..02a82f25
--- /dev/null
+++ b/subx/vim_errors.subx
@@ -0,0 +1,34 @@
+# test file for Vim highlighting
+
+## unindented lines below should all get Warn highlighting in .subx files
+# indented lines should get no highlighting
+
+# raw displacement in jump/call instructions
+e8 10/disp32
+e8 . 10/disp32
+e8/call . -10/disp32
+e8/call . 0x10/disp32
+e9/jump . 10/disp8
+e9/jump . -10/disp8
+e9/jump . f0/disp8
+7c/jump . 10/disp8
+7c/jump . -10/disp8
+eb/jump . 10/disp16
+eb/jump . -10/disp16
+0f/foo 8e/jump . 10/disp16
+0f/foo 8e/jump . -10/disp16
+
+## unindented lines below should all get Error highlighting in .subx files
+# indented lines should get no highlighting
+
+# mismatch in label type (call to '$' or jump to non-'$')
+e8 $foo/disp32
+e8 . $foo/disp32
+e8/call . $foo/disp32
+e8/call . $foo/disp32
+e9/jump . foo/disp8
+  e9/jump . $foo/disp8
+  e9/jump . . $foo/disp8
+7c/jump . foo/disp8
+eb/jump . foo/disp16
+0f/foo 8e/jump . foo/disp16