Initializing a global array of labels in llvm-IR - llvm-ir

I'm porting a legacy system over to llvm. To supoort all existing functionality I need to store addresses to arbitrary places in the code, so that I later can find those locations in the executable. I could probably use debug data, but my target currently doesn't support dwarf.
So I start out with
__builtin_region_start("Tag");
/* do something */
__builtin_region_stop("Tag");
/*do something else */
__builtin_region_start("Tag2");
/* do something */
__builtin_region_stop("Tag2");
/*do something else */
__builtin_region_start("Tag");
/* do something */
__builtin_region_stop("Tag");
/*do something else */
In llvm I want to rewrite it to something like:
#Tag_start = dso_local global [2 x ptr] , [ptr #lbl1, ptr #lbl5]
#Tag_stop = dso_local global [2 x ptr] , [ptr #lbl2, ptr #lbl6]
#Tag2_start = dso_local global [1 x ptr] , [ptr #lbl3]
#Tag2_stop = dso_local global [1 x ptr] , [ptr #lbl4]
lbl1:
/* do something */
lbl2:
/*do something else */
lbl3:
/* do something */
lbl4:
/*do something else */
lbl5:
/* do something */
lbl6:
/*do something else */
I can then extract what I need from the object file after it has been relocated. Basically:
Tag: start[<address>,<address>],stop[<address>,<address>]
Tag2: start[<address>], stop[<address>]
I can create the labels and get handles to them as BlockAddress, but I don't seem to be able to create the global object, since I can't get the global variables type to line up with anything derived from the block address.
BlockAddress dumps as an i8*, but that is not a scalar so I can't use that to build a constant for the initializer.
Looking at code examples from source like (void *)myptr=&&lbl; dumps out as type ptr rather than i8* but I haven't found a way to create such a type from inside llvm. There is an LabelTy in the type system, but I haven't found how to create such types, so I haven't been able to see if it gets me closer to what I want to do.
Any Ideas?

Related

Cannot replace pointer via a struct method

Got a struct method that returns a pointer:
func (d *DataMap) Get(p Coord) *CellData {
return &d.Data[p.X+(p.Y*d.Size)]
}
The d.Data is an array of CellData which is a struct with several fields. With this method I can modify the inner value of each field, ie:
example.Get(p).Something = 123
But I cannot do something like this:
example.Get(p) = *yada (yada is a *CellData)
Where I want to replace the pointer with another pointer I get:
cannot assign to example.Get(p)(undefined)
What am I doing wrong? The output of the function is defined, dont' know why I'm getting that error. Right now I fixed this by accessing the array directly.
Thanks.
Get returns a pointer, so if you want to store into whatever that pointer is pointing to, you need to add a * (pointer dereference) at the beginning:
*(example.Get(p)) = *yada

Why does Flow let you cast an Any type to, say, a Number in this example?

In the Flow docs about Any type, they say that it is not safe to use Any type and that if you do you should cast results of operations with that type as soon as possible to avoid Any leaking to other variables in your code. This casting is done in the line let foo: number = obj.foo below.
// #flow
function fn(obj: any) /* (:number) */ {
let foo: number = obj.foo;
let bar /* (:number) */ = foo * 2;
return bar;
}
let bar /* (:number) */ = fn({ foo: 2 });
let baz /* (:string) */ = "baz:" + bar;
The argument to fn, for parameter obj can be anything. It's properties can have anything. Why does flow let you even do the above-mentioned casting? You cannot guarantee that foo will be a number since obj.foo can be anything.
As noted in the comments, the entire point of any is to allow "any" operation to be performed on it.
This is basically like asking why your phone doesn't audibly ring when it's in silent mode. That's the point of silent mode. Change the ringer volume to something else (i.e. use mixed) if you'd like it to make noise.

Multiple function signatures in externs rule

I am writing closure externs for WebAssembly.
For function WebAssembly.instantiate, it has 2 function signatures.
Promise<{module:WebAssembly.Module, instance:WebAssembly.Instance}>
instantiate(BufferSource bytes [, importObject])
Promise<WebAssembly.Instance> instantiate(moduleObject [, importObject])
How to declare both rules in closure externs?
Reference:
https://github.com/WebAssembly/design/blob/master/JS.md#webassemblyinstantiate
You can specify that argument and result are union of two different types. See https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler about how to specify types.
Here is a simple example of such a function:
/**
* #param {string|number} value
* #return {string|number}
*/
ambiguous = function(value) {
if (typeof value == 'string') {
return value+' is string';
} else if (typeof value == 'number') {
return value+1;
} else throw new Error();
};
For your WebAssembly.instantiate function you will of course have more complex types than string and number. I don't know how you would specify the Promise types, I don't recognize the syntax shown for those, and I doubt closure compiler will parse that as-is. The extern then looks something like this (with bogus types for the Promises).
/**
#param (!BufferSource|!WebAssembly.Module) arg1 either a BufferSource or a module
#param Object= importObject optional object to import
#return (!PromiseType1|!PromiseType2)
*/
WebAssembly.instantiate = function(arg1, importObject) {};
The ! symbol is used to indicate a non-null object. If these can be null then leave that out. The = symbol after Object= means it can be undefined.
When using the results of this function you will need to test what type of thing you got using instanceof or some other method. Otherwise the compiler only knows the result is one of the two possible types. If not using instanceof, you can use type casting to tell the compiler that you know what the type is, see end of that page referenced above.
An example of a function from closure-library that has a union type in both its argument and its result is goog.array.find. The source for goog.array.find is available. Note that the angle brackets <> are used for the template type feature of the compiler.

how can I just ignored the specified error in jsHint?

I use require.js in my job, when I run jshint
it will tell me this:
line 11, col 1, 'define' is not defined.
I want to do this:
if is define not defined, ignore,
if is others not defined, tell me the error
how can I write in jshint.rc?
I suppose this is because define is actually defined, just not in that file.
You need to tell jsHint that define is a valid global symbol.
Add this line at the beginning:
/* global define */
or
/* global define,$,require,whatever */
to prime the global symbol check table.
In jshint.rc, you can set:
{
"define" : true
}
or if define is not a known library,
{
"predef" : [
"define"
]
}
(see for example this link).

Is there a way to do associative arrays in REXX?

I have some Perl code (for performance analysis) first developed under Linux which now needs to be ported to the mainframe. Apparently REXX is the scripting language of choice on that platform but this Perl script relies heavily on associative arrays (basically arrays where the index is a string).
Is there a way that in REXX? How would I code up something like:
$arr{"Pax"} = "Diablo";
$arr{"Bob"} = "Dylan";
print $arr{"Pax"} . "\n";
if (defined $arr{"no"}) {
print "Yes\n";
} else {
print "No\n";
}
You can use stem variables, not exactly like arrays but very similar
/* REXX */
NAME = PAX
ARRAY.NAME = "DIABLO"
NAME = BOB
ARRAY.NAME = "DYLAN"
NAME = 'PAX'
SAY "ARRAY.PAX " IS ARRAY.NAME
NAME = 'BOB'
SAY "ARRAY.BOB " IS ARRAY.NAME
NAME = 'SANDY'
SAY "ARRAY.SANDY " IS ARRAY.NAME
IF ARRAY.NAME = "ARRAY.SANDY" THEN SAY "ARRAY.SANDY IS EMPTY"
The above Rexx will print
ARRAY.PAX IS DIABLO
ARRAY.BOB IS DYLAN
ARRAY.SANDY IS ARRAY.SANDY
ARRAY.SANDY IS EMPTY
They can also be compound like a.b.c
A stem variable if empty will return itself.
There is no way to iterate of a stem that does not use consecutive numbers as the index that I know of.
IBM Manual with reference to Stem variables
Perl is available as an extra free feature for ZOS IBM Ported Tools for z/OS
I just want to add a bit more to the answer given by Deuian.
I agree, REXX stem variables
are the answer.
Simple REXX variables default to their own name. For example:
/* REXX */
SAY X
will print "X" until X is assigned some other value:
/* REXX */
X = 'A'
SAY X
will print "A".
No big surprise so far. Stem variables are a bit different. The
head of the stem is never evaluated, only the bit after the initial dot
is.
To illustrate:
/* REXX */
X. = 'empty' /* all unassigned stem values take on this value */
A. = 'nil'
B = 'A' /* simple variable B is assigned value A */
X = 'A' /* simple variable X is assigned value A */
SAY X.A /* prints: empty */
X.A = 'hello' /* Stem X. associates value of A with 'hello' */
SAY X.A /* prints: hello */
SAY X.B /* prints: hello */
SAY X.X /* prints: hello */
Notice the X and the A stem names are not evaluated, however, the
X and A variables appearing after them are. Some people find this a
bit confusing - think about it for a while and it makes
great sense.
The Z/OS version of REXX does not provide a natural way to iterate over
a stem variable. The easiest way to do this is to build your own index.
For example:
/* REXX */
X. = ''
DO I = 1 TO 10
J = RANDOM(100, 500) /* Random # 100..500 */
X.INDEX = X.INDEX J /* concatinate J's with 1 space between */
X.J = 'was picked' /* Associate 'was picked' with whatever J evalauates to */
END
DO I = 1 TO WORDS(X.INDEX) /* Number of blank delimited 'words' */
J = WORD(X.INDEX, I) /* Extract 1 'word' at a time */
SAY J X.J /* Print 'word' and its associated value */
END
Pretty trivial but illustrates the idea. Just be sure that INDEX (or whatever name you
choose) to hold the indexing names never pops up as an associative value! If this is a possibility, use some other variable to hold the index.
Last point. Notice each of my examples begins with /* REXX */ you may find
that this needs to be the first line of your REXX programs under Z/OS.

Resources